Changes to allow Samba to return the same error code as Windows NT.
[Samba.git] / source / smbd / server.c
blobaaf62fdcad94f802793cb37fca95f92f33fef91c
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB server routines
5 Copyright (C) Andrew Tridgell 1992-1997
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
23 #include "trans2.h"
25 pstring servicesf = CONFIGFILE;
26 extern pstring debugf;
27 extern pstring sesssetup_user;
28 extern fstring myworkgroup;
30 char *InBuffer = NULL;
31 char *OutBuffer = NULL;
32 char *last_inbuf = NULL;
34 int am_parent = 1;
35 int atexit_set = 0;
37 /* the last message the was processed */
38 int last_message = -1;
40 /* a useful macro to debug the last message processed */
41 #define LAST_MESSAGE() smb_fn_name(last_message)
43 extern pstring scope;
44 extern int DEBUGLEVEL;
45 extern int case_default;
46 extern BOOL case_sensitive;
47 extern BOOL case_preserve;
48 extern BOOL use_mangled_map;
49 extern BOOL short_case_preserve;
50 extern BOOL case_mangle;
51 extern time_t smb_last_time;
53 extern int smb_read_error;
55 extern pstring user_socket_options;
57 connection_struct Connections[MAX_CONNECTIONS];
58 files_struct Files[MAX_OPEN_FILES];
61 * Indirection for file fd's. Needed as POSIX locking
62 * is based on file/process, not fd/process.
64 file_fd_struct FileFd[MAX_OPEN_FILES];
65 int max_file_fd_used = 0;
67 extern int Protocol;
69 /*
70 * Size of data we can send to client. Set
71 * by the client for all protocols above CORE.
72 * Set by us for CORE protocol.
74 int max_send = BUFFER_SIZE;
76 * Size of the data we can receive. Set by us.
77 * Can be modified by the max xmit parameter.
79 int max_recv = BUFFER_SIZE;
81 /* a fnum to use when chaining */
82 int chain_fnum = -1;
84 /* number of open connections */
85 static int num_connections_open = 0;
87 extern fstring remote_machine;
89 pstring OriginalDir;
91 /* these can be set by some functions to override the error codes */
92 int unix_ERR_class=SUCCESS;
93 int unix_ERR_code=0;
96 extern int extra_time_offset;
98 extern pstring myhostname;
100 static int find_free_connection(int hash);
102 /* for readability... */
103 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
104 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
105 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
106 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
107 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
109 /****************************************************************************
110 when exiting, take the whole family
111 ****************************************************************************/
112 void *dflt_sig(void)
114 exit_server("caught signal");
115 return 0; /* Keep -Wall happy :-) */
117 /****************************************************************************
118 Send a SIGTERM to our process group.
119 *****************************************************************************/
120 void killkids(void)
122 if(am_parent) kill(0,SIGTERM);
125 /****************************************************************************
126 change a dos mode to a unix mode
127 base permission for files:
128 everybody gets read bit set
129 dos readonly is represented in unix by removing everyone's write bit
130 dos archive is represented in unix by the user's execute bit
131 dos system is represented in unix by the group's execute bit
132 dos hidden is represented in unix by the other's execute bit
133 Then apply create mask,
134 then add force bits.
135 base permission for directories:
136 dos directory is represented in unix by unix's dir bit and the exec bit
137 Then apply create mask,
138 then add force bits.
139 ****************************************************************************/
140 mode_t unix_mode(int cnum,int dosmode)
142 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
144 if ( !IS_DOS_READONLY(dosmode) )
145 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
147 if (IS_DOS_DIR(dosmode)) {
148 /* We never make directories read only for the owner as under DOS a user
149 can always create a file in a read-only directory. */
150 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
151 /* Apply directory mask */
152 result &= lp_dir_mode(SNUM(cnum));
153 /* Add in force bits */
154 result |= lp_force_dir_mode(SNUM(cnum));
155 } else {
156 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
157 result |= S_IXUSR;
159 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
160 result |= S_IXGRP;
162 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
163 result |= S_IXOTH;
165 /* Apply mode mask */
166 result &= lp_create_mode(SNUM(cnum));
167 /* Add in force bits */
168 result |= lp_force_create_mode(SNUM(cnum));
170 return(result);
174 /****************************************************************************
175 change a unix mode to a dos mode
176 ****************************************************************************/
177 int dos_mode(int cnum,char *path,struct stat *sbuf)
179 int result = 0;
180 extern struct current_user current_user;
182 DEBUG(5,("dos_mode: %d %s\n", cnum, path));
184 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
185 if (!((sbuf->st_mode & S_IWOTH) ||
186 Connections[cnum].admin_user ||
187 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
188 ((sbuf->st_mode & S_IWGRP) &&
189 in_group(sbuf->st_gid,current_user.gid,
190 current_user.ngroups,current_user.igroups))))
191 result |= aRONLY;
192 } else {
193 if ((sbuf->st_mode & S_IWUSR) == 0)
194 result |= aRONLY;
197 if (MAP_ARCHIVE(cnum) && ((sbuf->st_mode & S_IXUSR) != 0))
198 result |= aARCH;
200 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
201 result |= aSYSTEM;
203 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
204 result |= aHIDDEN;
206 if (S_ISDIR(sbuf->st_mode))
207 result = aDIR | (result & aRONLY);
209 #if LINKS_READ_ONLY
210 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
211 result |= aRONLY;
212 #endif
214 /* hide files with a name starting with a . */
215 if (lp_hide_dot_files(SNUM(cnum)))
217 char *p = strrchr(path,'/');
218 if (p)
219 p++;
220 else
221 p = path;
223 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
224 result |= aHIDDEN;
227 /* Optimization : Only call is_hidden_path if it's not already
228 hidden. */
229 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(cnum,path))
231 result |= aHIDDEN;
234 DEBUG(5,("dos_mode returning "));
236 if (result & aHIDDEN) DEBUG(5, ("h"));
237 if (result & aRONLY ) DEBUG(5, ("r"));
238 if (result & aSYSTEM) DEBUG(5, ("s"));
239 if (result & aDIR ) DEBUG(5, ("d"));
240 if (result & aARCH ) DEBUG(5, ("a"));
242 DEBUG(5,("\n"));
244 return(result);
248 /*******************************************************************
249 chmod a file - but preserve some bits
250 ********************************************************************/
251 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
253 struct stat st1;
254 int mask=0;
255 int tmp;
256 int unixmode;
258 if (!st) {
259 st = &st1;
260 if (sys_stat(fname,st)) return(-1);
263 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
265 if (dos_mode(cnum,fname,st) == dosmode) return(0);
267 unixmode = unix_mode(cnum,dosmode);
269 /* preserve the s bits */
270 mask |= (S_ISUID | S_ISGID);
272 /* preserve the t bit */
273 #ifdef S_ISVTX
274 mask |= S_ISVTX;
275 #endif
277 /* possibly preserve the x bits */
278 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
279 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
280 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
282 unixmode |= (st->st_mode & mask);
284 /* if we previously had any r bits set then leave them alone */
285 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
286 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
287 unixmode |= tmp;
290 /* if we previously had any w bits set then leave them alone
291 if the new mode is not rdonly */
292 if (!IS_DOS_READONLY(dosmode) &&
293 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
294 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
295 unixmode |= tmp;
298 return(sys_chmod(fname,unixmode));
302 /****************************************************************************
303 check if two filenames are equal
305 this needs to be careful about whether we are case sensitive
306 ****************************************************************************/
307 static BOOL fname_equal(char *name1, char *name2)
309 int l1 = strlen(name1);
310 int l2 = strlen(name2);
312 /* handle filenames ending in a single dot */
313 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
315 BOOL ret;
316 name1[l1-1] = 0;
317 ret = fname_equal(name1,name2);
318 name1[l1-1] = '.';
319 return(ret);
322 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
324 BOOL ret;
325 name2[l2-1] = 0;
326 ret = fname_equal(name1,name2);
327 name2[l2-1] = '.';
328 return(ret);
331 /* now normal filename handling */
332 if (case_sensitive)
333 return(strcmp(name1,name2) == 0);
335 return(strequal(name1,name2));
339 /****************************************************************************
340 mangle the 2nd name and check if it is then equal to the first name
341 ****************************************************************************/
342 static BOOL mangled_equal(char *name1, char *name2)
344 pstring tmpname;
346 if (is_8_3(name2, True))
347 return(False);
349 strcpy(tmpname,name2);
350 mangle_name_83(tmpname);
352 return(strequal(name1,tmpname));
356 /****************************************************************************
357 scan a directory to find a filename, matching without case sensitivity
359 If the name looks like a mangled name then try via the mangling functions
360 ****************************************************************************/
361 static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache)
363 void *cur_dir;
364 char *dname;
365 BOOL mangled;
366 pstring name2;
368 mangled = is_mangled(name);
370 /* handle null paths */
371 if (*path == 0)
372 path = ".";
374 if (docache && (dname = DirCacheCheck(path,name,SNUM(cnum)))) {
375 strcpy(name, dname);
376 return(True);
379 if (mangled)
380 check_mangled_stack(name);
382 /* open the directory */
383 if (!(cur_dir = OpenDir(cnum, path, True)))
385 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
386 return(False);
389 /* now scan for matching names */
390 while ((dname = ReadDirName(cur_dir)))
392 if (*dname == '.' &&
393 (strequal(dname,".") || strequal(dname,"..")))
394 continue;
396 strcpy(name2,dname);
397 if (!name_map_mangle(name2,False,SNUM(cnum))) continue;
399 if ((mangled && mangled_equal(name,name2))
400 || fname_equal(name, dname))
402 /* we've found the file, change it's name and return */
403 if (docache) DirCacheAdd(path,name,dname,SNUM(cnum));
404 strcpy(name, dname);
405 CloseDir(cur_dir);
406 return(True);
410 CloseDir(cur_dir);
411 return(False);
414 /****************************************************************************
415 This routine is called to convert names from the dos namespace to unix
416 namespace. It needs to handle any case conversions, mangling, format
417 changes etc.
419 We assume that we have already done a chdir() to the right "root" directory
420 for this service.
422 The function will return False if some part of the name except for the last
423 part cannot be resolved
425 If the saved_last_component != 0, then the unmodified last component
426 of the pathname is returned there. This is used in an exceptional
427 case in reply_mv (so far). If saved_last_component == 0 then nothing
428 is returned there.
430 The bad_path arg is set to True if the filename walk failed. This is
431 used to pick the correct error code to return between ENOENT and ENOTDIR
432 as Windows applications depend on ERRbadpath being returned if a component
433 of a pathname does not exist.
434 ****************************************************************************/
435 BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path)
437 struct stat st;
438 char *start, *end;
439 pstring dirpath;
440 int saved_errno;
442 *dirpath = 0;
443 *bad_path = False;
445 if(saved_last_component)
446 *saved_last_component = 0;
448 /* convert to basic unix format - removing \ chars and cleaning it up */
449 unix_format(name);
450 unix_clean_name(name);
452 /* names must be relative to the root of the service - trim any leading /.
453 also trim trailing /'s */
454 trim_string(name,"/","/");
457 * Ensure saved_last_component is valid even if file exists.
459 if(saved_last_component) {
460 end = strrchr(name, '/');
461 if(end)
462 strcpy(saved_last_component, end + 1);
463 else
464 strcpy(saved_last_component, name);
467 if (!case_sensitive &&
468 (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
469 strnorm(name);
471 /* check if it's a printer file */
472 if (Connections[cnum].printer)
474 if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
476 char *s;
477 fstring name2;
478 sprintf(name2,"%.6s.XXXXXX",remote_machine);
479 /* sanitise the name */
480 for (s=name2 ; *s ; s++)
481 if (!issafe(*s)) *s = '_';
482 strcpy(name,(char *)mktemp(name2));
484 return(True);
487 /* stat the name - if it exists then we are all done! */
488 if (sys_stat(name,&st) == 0)
489 return(True);
491 saved_errno = errno;
493 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
495 /* a special case - if we don't have any mangling chars and are case
496 sensitive then searching won't help */
497 if (case_sensitive && !is_mangled(name) &&
498 !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
499 return(False);
501 /* now we need to recursively match the name against the real
502 directory structure */
504 start = name;
505 while (strncmp(start,"./",2) == 0)
506 start += 2;
508 /* now match each part of the path name separately, trying the names
509 as is first, then trying to scan the directory for matching names */
510 for (;start;start = (end?end+1:(char *)NULL))
512 /* pinpoint the end of this section of the filename */
513 end = strchr(start, '/');
515 /* chop the name at this point */
516 if (end) *end = 0;
518 if(saved_last_component != 0)
519 strcpy(saved_last_component, end ? end + 1 : start);
521 /* check if the name exists up to this point */
522 if (sys_stat(name, &st) == 0)
524 /* it exists. it must either be a directory or this must be
525 the last part of the path for it to be OK */
526 if (end && !(st.st_mode & S_IFDIR))
528 /* an intermediate part of the name isn't a directory */
529 DEBUG(5,("Not a dir %s\n",start));
530 *end = '/';
531 return(False);
534 else
536 pstring rest;
538 *rest = 0;
540 /* remember the rest of the pathname so it can be restored
541 later */
542 if (end) strcpy(rest,end+1);
544 /* try to find this part of the path in the directory */
545 if (strchr(start,'?') || strchr(start,'*') ||
546 !scan_directory(dirpath, start, cnum, end?True:False))
548 if (end)
550 /* an intermediate part of the name can't be found */
551 DEBUG(5,("Intermediate not found %s\n",start));
552 *end = '/';
553 /* We need to return the fact that the intermediate
554 name resolution failed. This is used to return an
555 error of ERRbadpath rather than ERRbadfile. Some
556 Windows applications depend on the difference between
557 these two errors.
559 *bad_path = True;
560 return(False);
563 /* just the last part of the name doesn't exist */
564 /* we may need to strupper() or strlower() it in case
565 this conversion is being used for file creation
566 purposes */
567 /* if the filename is of mixed case then don't normalise it */
568 if (!case_preserve &&
569 (!strhasupper(start) || !strhaslower(start)))
570 strnorm(start);
572 /* check on the mangled stack to see if we can recover the
573 base of the filename */
574 if (is_mangled(start))
575 check_mangled_stack(start);
577 DEBUG(5,("New file %s\n",start));
578 return(True);
581 /* restore the rest of the string */
582 if (end)
584 strcpy(start+strlen(start)+1,rest);
585 end = start + strlen(start);
589 /* add to the dirpath that we have resolved so far */
590 if (*dirpath) strcat(dirpath,"/");
591 strcat(dirpath,start);
593 /* restore the / that we wiped out earlier */
594 if (end) *end = '/';
597 /* the name has been resolved */
598 DEBUG(5,("conversion finished %s\n",name));
599 return(True);
603 /****************************************************************************
604 normalise for DOS usage
605 ****************************************************************************/
606 static void disk_norm(int *bsize,int *dfree,int *dsize)
608 /* check if the disk is beyond the max disk size */
609 int maxdisksize = lp_maxdisksize();
610 if (maxdisksize) {
611 /* convert to blocks - and don't overflow */
612 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
613 if (*dsize > maxdisksize) *dsize = maxdisksize;
614 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
615 applications getting
616 div by 0 errors */
619 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
621 *dfree /= 2;
622 *dsize /= 2;
623 *bsize *= 2;
624 if (*bsize > WORDMAX )
626 *bsize = WORDMAX;
627 if (*dsize > WORDMAX)
628 *dsize = WORDMAX;
629 if (*dfree > WORDMAX)
630 *dfree = WORDMAX;
631 break;
636 /****************************************************************************
637 return number of 1K blocks available on a path and total number
638 ****************************************************************************/
639 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
641 char *df_command = lp_dfree_command();
642 int dfree_retval;
643 #ifdef QUOTAS
644 int dfreeq_retval;
645 int dfreeq = 0;
646 int bsizeq = *bsize;
647 int dsizeq = *dsize;
648 #endif
650 #ifndef NO_STATFS
651 #ifdef USE_STATVFS
652 struct statvfs fs;
653 #else
654 #ifdef ULTRIX
655 struct fs_data fs;
656 #else
657 struct statfs fs;
658 #endif
659 #endif
660 #endif
662 /* possibly use system() to get the result */
663 if (df_command && *df_command)
665 int ret;
666 pstring syscmd;
667 pstring outfile;
669 sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
670 sprintf(syscmd,"%s %s",df_command,path);
671 standard_sub_basic(syscmd);
673 ret = smbrun(syscmd,outfile,False);
674 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
677 FILE *f = fopen(outfile,"r");
678 *dsize = 0;
679 *dfree = 0;
680 *bsize = 1024;
681 if (f)
683 fscanf(f,"%d %d %d",dsize,dfree,bsize);
684 fclose(f);
686 else
687 DEBUG(0,("Can't open %s\n",outfile));
690 unlink(outfile);
691 disk_norm(bsize,dfree,dsize);
692 dfree_retval = ((*bsize)/1024)*(*dfree);
693 #ifdef QUOTAS
694 /* Ensure we return the min value between the users quota and
695 what's free on the disk. Thanks to Albrecht Gebhardt
696 <albrecht.gebhardt@uni-klu.ac.at> for this fix.
698 if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
700 disk_norm(&bsizeq, &dfreeq, &dsizeq);
701 dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
702 dfree_retval = ( dfree_retval < dfreeq_retval ) ?
703 dfree_retval : dfreeq_retval ;
704 /* maybe dfree and dfreeq are calculated using different bsizes
705 so convert dfree from bsize into bsizeq */
706 *dfree = ((*dfree) * (*bsize)) / (bsizeq);
707 *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
708 *bsize = bsizeq;
709 *dsize = dsizeq;
711 #endif
712 return(dfree_retval);
715 #ifdef NO_STATFS
716 DEBUG(1,("Warning - no statfs function\n"));
717 return(1);
718 #else
719 #ifdef STATFS4
720 if (statfs(path,&fs,sizeof(fs),0) != 0)
721 #else
722 #ifdef USE_STATVFS
723 if (statvfs(path, &fs))
724 #else
725 #ifdef STATFS3
726 if (statfs(path,&fs,sizeof(fs)) == -1)
727 #else
728 if (statfs(path,&fs) == -1)
729 #endif /* STATFS3 */
730 #endif /* USE_STATVFS */
731 #endif /* STATFS4 */
733 DEBUG(3,("dfree call failed code errno=%d\n",errno));
734 *bsize = 1024;
735 *dfree = 1;
736 *dsize = 1;
737 return(((*bsize)/1024)*(*dfree));
740 #ifdef ULTRIX
741 *bsize = 1024;
742 *dfree = fs.fd_req.bfree;
743 *dsize = fs.fd_req.btot;
744 #else
745 #ifdef USE_STATVFS
746 *bsize = fs.f_frsize;
747 #else
748 #ifdef USE_F_FSIZE
749 /* eg: osf1 has f_fsize = fundamental filesystem block size,
750 f_bsize = optimal transfer block size (MX: 94-04-19) */
751 *bsize = fs.f_fsize;
752 #else
753 *bsize = fs.f_bsize;
754 #endif /* STATFS3 */
755 #endif /* USE_STATVFS */
757 #ifdef STATFS4
758 *dfree = fs.f_bfree;
759 #else
760 *dfree = fs.f_bavail;
761 #endif /* STATFS4 */
762 *dsize = fs.f_blocks;
763 #endif /* ULTRIX */
765 #if defined(SCO) || defined(ISC) || defined(MIPS)
766 *bsize = 512;
767 #endif
769 /* handle rediculous bsize values - some OSes are broken */
770 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
772 disk_norm(bsize,dfree,dsize);
774 if (*bsize < 256)
775 *bsize = 512;
776 if ((*dsize)<1)
778 DEBUG(0,("dfree seems to be broken on your system\n"));
779 *dsize = 20*1024*1024/(*bsize);
780 *dfree = MAX(1,*dfree);
782 dfree_retval = ((*bsize)/1024)*(*dfree);
783 #ifdef QUOTAS
784 /* Ensure we return the min value between the users quota and
785 what's free on the disk. Thanks to Albrecht Gebhardt
786 <albrecht.gebhardt@uni-klu.ac.at> for this fix.
788 if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
790 disk_norm(&bsizeq, &dfreeq, &dsizeq);
791 dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
792 dfree_retval = ( dfree_retval < dfreeq_retval ) ?
793 dfree_retval : dfreeq_retval ;
794 /* maybe dfree and dfreeq are calculated using different bsizes
795 so convert dfree from bsize into bsizeq */
796 *dfree = ((*dfree) * (*bsize)) / (bsizeq);
797 *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
798 *bsize = bsizeq;
799 *dsize = dsizeq;
801 #endif
802 return(dfree_retval);
803 #endif
807 /****************************************************************************
808 wrap it to get filenames right
809 ****************************************************************************/
810 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
812 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
817 /****************************************************************************
818 check a filename - possibly caling reducename
820 This is called by every routine before it allows an operation on a filename.
821 It does any final confirmation necessary to ensure that the filename is
822 a valid one for the user to access.
823 ****************************************************************************/
824 BOOL check_name(char *name,int cnum)
826 BOOL ret;
828 errno = 0;
830 if( IS_VETO_PATH(cnum, name))
832 DEBUG(5,("file path name %s vetoed\n",name));
833 return(0);
836 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
838 /* Check if we are allowing users to follow symlinks */
839 /* Patch from David Clerc <David.Clerc@cui.unige.ch>
840 University of Geneva */
842 if (!lp_symlinks(SNUM(cnum)))
844 struct stat statbuf;
845 if ( (sys_lstat(name,&statbuf) != -1) &&
846 (S_ISLNK(statbuf.st_mode)) )
848 DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
849 ret=0;
853 if (!ret)
854 DEBUG(5,("check_name on %s failed\n",name));
856 return(ret);
859 /****************************************************************************
860 check a filename - possibly caling reducename
861 ****************************************************************************/
862 static void check_for_pipe(char *fname)
864 /* special case of pipe opens */
865 char s[10];
866 StrnCpy(s,fname,9);
867 strlower(s);
868 if (strstr(s,"pipe/"))
870 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
871 unix_ERR_class = ERRSRV;
872 unix_ERR_code = ERRaccess;
876 /****************************************************************************
877 fd support routines - attempt to do a sys_open
878 ****************************************************************************/
880 int fd_attempt_open(char *fname, int flags, int mode)
882 int fd = sys_open(fname,flags,mode);
884 /* Fix for files ending in '.' */
885 if((fd == -1) && (errno == ENOENT) &&
886 (strchr(fname,'.')==NULL))
888 strcat(fname,".");
889 fd = sys_open(fname,flags,mode);
892 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
893 if ((fd == -1) && (errno == ENAMETOOLONG))
895 int max_len;
896 char *p = strrchr(fname, '/');
898 if (p == fname) /* name is "/xxx" */
900 max_len = pathconf("/", _PC_NAME_MAX);
901 p++;
903 else if ((p == NULL) || (p == fname))
905 p = fname;
906 max_len = pathconf(".", _PC_NAME_MAX);
908 else
910 *p = '\0';
911 max_len = pathconf(fname, _PC_NAME_MAX);
912 *p = '/';
913 p++;
915 if (strlen(p) > max_len)
917 char tmp = p[max_len];
919 p[max_len] = '\0';
920 if ((fd = sys_open(fname,flags,mode)) == -1)
921 p[max_len] = tmp;
924 #endif
925 return fd;
928 /****************************************************************************
929 fd support routines - attempt to find an already open file by dev
930 and inode - increments the ref_count of the returned file_fd_struct *.
931 ****************************************************************************/
932 file_fd_struct *fd_get_already_open(struct stat *sbuf)
934 int i;
935 file_fd_struct *fd_ptr;
937 if(sbuf == 0)
938 return 0;
940 for(i = 0; i <= max_file_fd_used; i++) {
941 fd_ptr = &FileFd[i];
942 if((fd_ptr->ref_count > 0) &&
943 (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
944 (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
945 fd_ptr->ref_count++;
946 DEBUG(3,
947 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
948 i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
949 return fd_ptr;
952 return 0;
955 /****************************************************************************
956 fd support routines - attempt to find a empty slot in the FileFd array.
957 Increments the ref_count of the returned entry.
958 ****************************************************************************/
959 file_fd_struct *fd_get_new()
961 int i;
962 file_fd_struct *fd_ptr;
964 for(i = 0; i < MAX_OPEN_FILES; i++) {
965 fd_ptr = &FileFd[i];
966 if(fd_ptr->ref_count == 0) {
967 fd_ptr->dev = (uint32)-1;
968 fd_ptr->inode = (uint32)-1;
969 fd_ptr->fd = -1;
970 fd_ptr->fd_readonly = -1;
971 fd_ptr->fd_writeonly = -1;
972 fd_ptr->real_open_flags = -1;
973 fd_ptr->ref_count++;
974 /* Increment max used counter if neccessary, cuts down
975 on search time when re-using */
976 if(i > max_file_fd_used)
977 max_file_fd_used = i;
978 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
979 i, fd_ptr->dev, fd_ptr->inode));
980 return fd_ptr;
983 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
984 n"));
985 return 0;
988 /****************************************************************************
989 fd support routines - attempt to re-open an already open fd as O_RDWR.
990 Save the already open fd (we cannot close due to POSIX file locking braindamage.
991 ****************************************************************************/
993 void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
995 int fd = sys_open( fname, O_RDWR, mode);
997 if(fd == -1)
998 return;
1000 if(fd_ptr->real_open_flags == O_RDONLY)
1001 fd_ptr->fd_readonly = fd_ptr->fd;
1002 if(fd_ptr->real_open_flags == O_WRONLY)
1003 fd_ptr->fd_writeonly = fd_ptr->fd;
1005 fd_ptr->fd = fd;
1006 fd_ptr->real_open_flags = O_RDWR;
1009 /****************************************************************************
1010 fd support routines - attempt to close the file referenced by this fd.
1011 Decrements the ref_count and returns it.
1012 ****************************************************************************/
1013 int fd_attempt_close(file_fd_struct *fd_ptr)
1015 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
1016 fd_ptr - &FileFd[0],
1017 fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
1018 fd_ptr->real_open_flags,
1019 fd_ptr->ref_count));
1020 if(fd_ptr->ref_count > 0) {
1021 fd_ptr->ref_count--;
1022 if(fd_ptr->ref_count == 0) {
1023 if(fd_ptr->fd != -1)
1024 close(fd_ptr->fd);
1025 if(fd_ptr->fd_readonly != -1)
1026 close(fd_ptr->fd_readonly);
1027 if(fd_ptr->fd_writeonly != -1)
1028 close(fd_ptr->fd_writeonly);
1029 fd_ptr->fd = -1;
1030 fd_ptr->fd_readonly = -1;
1031 fd_ptr->fd_writeonly = -1;
1032 fd_ptr->real_open_flags = -1;
1033 fd_ptr->dev = (uint32)-1;
1034 fd_ptr->inode = (uint32)-1;
1037 return fd_ptr->ref_count;
1040 /****************************************************************************
1041 open a file
1042 ****************************************************************************/
1043 static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
1045 extern struct current_user current_user;
1046 pstring fname;
1047 struct stat statbuf;
1048 file_fd_struct *fd_ptr;
1050 Files[fnum].open = False;
1051 Files[fnum].fd_ptr = 0;
1052 errno = EPERM;
1054 strcpy(fname,fname1);
1056 /* check permissions */
1057 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
1059 DEBUG(3,("Permission denied opening %s\n",fname));
1060 check_for_pipe(fname);
1061 return;
1064 /* this handles a bug in Win95 - it doesn't say to create the file when it
1065 should */
1066 if (Connections[cnum].printer)
1067 flags |= O_CREAT;
1070 if (flags == O_WRONLY)
1071 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
1074 #if UTIME_WORKAROUND
1075 /* XXXX - is this OK?? */
1076 /* this works around a utime bug but can cause other problems */
1077 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
1078 sys_unlink(fname);
1079 #endif
1082 * Ensure we have a valid struct stat so we can search the
1083 * open fd table.
1085 if(sbuf == 0) {
1086 if(stat(fname, &statbuf) < 0) {
1087 if(errno != ENOENT) {
1088 DEBUG(3,("Error doing stat on file %s (%s)\n",
1089 fname,strerror(errno)));
1091 check_for_pipe(fname);
1092 return;
1094 sbuf = 0;
1095 } else {
1096 sbuf = &statbuf;
1101 * Check to see if we have this file already
1102 * open. If we do, just use the already open fd and increment the
1103 * reference count (fd_get_already_open increments the ref_count).
1105 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
1107 int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
1109 /* File was already open. */
1110 if((flags & O_CREAT) && (flags & O_EXCL)) {
1111 fd_ptr->ref_count--;
1112 errno = EEXIST;
1113 return;
1117 * If not opened O_RDWR try
1118 * and do that here - a chmod may have been done
1119 * between the last open and now.
1121 if(fd_ptr->real_open_flags != O_RDWR)
1122 fd_attempt_reopen(fname, mode, fd_ptr);
1125 * Ensure that if we wanted write access
1126 * it has been opened for write, and if we wanted read it
1127 * was open for read.
1129 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1130 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1131 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1132 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1133 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1134 check_for_pipe(fname);
1135 fd_ptr->ref_count--;
1136 return;
1139 } else {
1140 int open_flags;
1141 /* We need to allocate a new file_fd_struct (this increments the
1142 ref_count). */
1143 if((fd_ptr = fd_get_new()) == 0)
1144 return;
1146 * Whatever the requested flags, attempt read/write access,
1147 * as we don't know what flags future file opens may require.
1148 * If this fails, try again with the required flags.
1149 * Even if we open read/write when only read access was
1150 * requested the setting of the can_write flag in
1151 * the file_struct will protect us from errant
1152 * write requests. We never need to worry about O_APPEND
1153 * as this is not set anywhere in Samba.
1155 fd_ptr->real_open_flags = O_RDWR;
1156 /* Set the flags as needed without the read/write modes. */
1157 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1158 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1160 * On some systems opening a file for R/W access on a read only
1161 * filesystems sets errno to EROFS.
1163 #ifdef EROFS
1164 if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1165 #else /* No EROFS */
1166 if((fd_ptr->fd == -1) && (errno == EACCES)) {
1167 #endif /* EROFS */
1168 if(flags & O_WRONLY) {
1169 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1170 fd_ptr->real_open_flags = O_WRONLY;
1171 } else {
1172 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1173 fd_ptr->real_open_flags = O_RDONLY;
1178 if ((fd_ptr->fd >=0) &&
1179 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1180 pstring dname;
1181 int dum1,dum2,dum3;
1182 char *p;
1183 strcpy(dname,fname);
1184 p = strrchr(dname,'/');
1185 if (p) *p = 0;
1186 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1187 lp_minprintspace(SNUM(cnum))) {
1188 fd_attempt_close(fd_ptr);
1189 Files[fnum].fd_ptr = 0;
1190 if(fd_ptr->ref_count == 0)
1191 sys_unlink(fname);
1192 errno = ENOSPC;
1193 return;
1197 if (fd_ptr->fd < 0)
1199 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1200 fname,strerror(errno),flags));
1201 /* Ensure the ref_count is decremented. */
1202 fd_attempt_close(fd_ptr);
1203 check_for_pipe(fname);
1204 return;
1207 if (fd_ptr->fd >= 0)
1209 if(sbuf == 0) {
1210 /* Do the fstat */
1211 if(fstat(fd_ptr->fd, &statbuf) == -1) {
1212 /* Error - backout !! */
1213 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1214 fd_ptr->fd, fname,strerror(errno)));
1215 /* Ensure the ref_count is decremented. */
1216 fd_attempt_close(fd_ptr);
1217 return;
1219 sbuf = &statbuf;
1221 /* Set the correct entries in fd_ptr. */
1222 fd_ptr->dev = (uint32)sbuf->st_dev;
1223 fd_ptr->inode = (uint32)sbuf->st_ino;
1225 Files[fnum].fd_ptr = fd_ptr;
1226 Connections[cnum].num_files_open++;
1227 Files[fnum].mode = sbuf->st_mode;
1228 GetTimeOfDay(&Files[fnum].open_time);
1229 Files[fnum].uid = current_user.id;
1230 Files[fnum].size = 0;
1231 Files[fnum].pos = -1;
1232 Files[fnum].open = True;
1233 Files[fnum].mmap_ptr = NULL;
1234 Files[fnum].mmap_size = 0;
1235 Files[fnum].can_lock = True;
1236 Files[fnum].can_read = ((flags & O_WRONLY)==0);
1237 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1238 Files[fnum].share_mode = 0;
1239 Files[fnum].print_file = Connections[cnum].printer;
1240 Files[fnum].modified = False;
1241 Files[fnum].cnum = cnum;
1242 string_set(&Files[fnum].name,dos_to_unix(fname,False));
1243 Files[fnum].wbmpx_ptr = NULL;
1246 * If the printer is marked as postscript output a leading
1247 * file identifier to ensure the file is treated as a raw
1248 * postscript file.
1249 * This has a similar effect as CtrlD=0 in WIN.INI file.
1250 * tim@fsg.com 09/06/94
1252 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
1253 Files[fnum].can_write)
1255 DEBUG(3,("Writing postscript line\n"));
1256 write_file(fnum,"%!\n",3);
1259 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1260 timestring(),Connections[cnum].user,fname,
1261 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1262 Connections[cnum].num_files_open,fnum));
1266 #if USE_MMAP
1267 /* mmap it if read-only */
1268 if (!Files[fnum].can_write)
1270 Files[fnum].mmap_size = file_size(fname);
1271 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1272 PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
1274 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1276 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1277 Files[fnum].mmap_ptr = NULL;
1280 #endif
1283 /*******************************************************************
1284 sync a file
1285 ********************************************************************/
1286 void sync_file(int fnum)
1288 #ifndef NO_FSYNC
1289 fsync(Files[fnum].fd_ptr->fd);
1290 #endif
1293 /****************************************************************************
1294 run a file if it is a magic script
1295 ****************************************************************************/
1296 static void check_magic(int fnum,int cnum)
1298 if (!*lp_magicscript(SNUM(cnum)))
1299 return;
1301 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1304 char *p;
1305 if (!(p = strrchr(Files[fnum].name,'/')))
1306 p = Files[fnum].name;
1307 else
1308 p++;
1310 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1311 return;
1315 int ret;
1316 pstring magic_output;
1317 pstring fname;
1318 strcpy(fname,Files[fnum].name);
1320 if (*lp_magicoutput(SNUM(cnum)))
1321 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1322 else
1323 sprintf(magic_output,"%s.out",fname);
1325 chmod(fname,0755);
1326 ret = smbrun(fname,magic_output,False);
1327 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1328 unlink(fname);
1333 /****************************************************************************
1334 close a file - possibly invalidating the read prediction
1335 ****************************************************************************/
1336 void close_file(int fnum)
1338 files_struct *fs_p = &Files[fnum];
1339 int cnum = fs_p->cnum;
1340 uint32 dev = fs_p->fd_ptr->dev;
1341 uint32 inode = fs_p->fd_ptr->inode;
1342 share_lock_token token;
1344 invalidate_read_prediction(fs_p->fd_ptr->fd);
1345 fs_p->open = False;
1346 Connections[cnum].num_files_open--;
1347 if(fs_p->wbmpx_ptr)
1349 free((char *)fs_p->wbmpx_ptr);
1350 fs_p->wbmpx_ptr = NULL;
1353 #if USE_MMAP
1354 if(fs_p->mmap_ptr)
1356 munmap(fs_p->mmap_ptr,fs_p->mmap_size);
1357 fs_p->mmap_ptr = NULL;
1359 #endif
1361 if (lp_share_modes(SNUM(cnum)))
1363 lock_share_entry( cnum, dev, inode, &token);
1364 del_share_mode(token, fnum);
1367 fd_attempt_close(fs_p->fd_ptr);
1369 if (lp_share_modes(SNUM(cnum)))
1370 unlock_share_entry( cnum, dev, inode, token);
1372 /* NT uses smbclose to start a print - weird */
1373 if (fs_p->print_file)
1374 print_file(fnum);
1376 /* check for magic scripts */
1377 check_magic(fnum,cnum);
1379 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1380 timestring(),Connections[cnum].user,fs_p->name,
1381 Connections[cnum].num_files_open));
1384 enum {AFAIL,AREAD,AWRITE,AALL};
1386 /*******************************************************************
1387 reproduce the share mode access table
1388 ********************************************************************/
1389 static int access_table(int new_deny,int old_deny,int old_mode,
1390 int share_pid,char *fname)
1392 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1394 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1395 if (old_deny == new_deny && share_pid == getpid())
1396 return(AALL);
1398 if (old_mode == 0) return(AREAD);
1400 /* the new smbpub.zip spec says that if the file extension is
1401 .com, .dll, .exe or .sym then allow the open. I will force
1402 it to read-only as this seems sensible although the spec is
1403 a little unclear on this. */
1404 if ((fname = strrchr(fname,'.'))) {
1405 if (strequal(fname,".com") ||
1406 strequal(fname,".dll") ||
1407 strequal(fname,".exe") ||
1408 strequal(fname,".sym"))
1409 return(AREAD);
1412 return(AFAIL);
1415 switch (new_deny)
1417 case DENY_WRITE:
1418 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1419 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1420 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1421 return(AFAIL);
1422 case DENY_READ:
1423 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1424 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1425 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1426 return(AFAIL);
1427 case DENY_NONE:
1428 if (old_deny==DENY_WRITE) return(AREAD);
1429 if (old_deny==DENY_READ) return(AWRITE);
1430 if (old_deny==DENY_NONE) return(AALL);
1431 return(AFAIL);
1433 return(AFAIL);
1436 /*******************************************************************
1437 check if the share mode on a file allows it to be deleted or unlinked
1438 return True if sharing doesn't prevent the operation
1439 ********************************************************************/
1440 BOOL check_file_sharing(int cnum,char *fname)
1442 int i;
1443 int ret = False;
1444 min_share_mode_entry *old_shares = 0;
1445 int num_share_modes;
1446 struct stat sbuf;
1447 share_lock_token token;
1448 int pid = getpid();
1450 if(!lp_share_modes(SNUM(cnum)))
1451 return True;
1453 if (stat(fname,&sbuf) == -1) return(True);
1455 lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token);
1456 num_share_modes = get_share_modes(cnum, token,
1457 (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares);
1459 for( i = 0; i < num_share_modes; i++)
1461 if (old_shares[i].share_mode != DENY_DOS)
1462 goto free_and_exit;
1464 if(old_shares[i].pid != pid)
1465 goto free_and_exit;
1468 /* XXXX exactly what share mode combinations should be allowed for
1469 deleting/renaming? */
1470 /* If we got here then either there were no share modes or
1471 all share modes were DENY_DOS and the pid == getpid() */
1472 ret = True;
1474 free_and_exit:
1476 unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token);
1477 if(old_shares != NULL)
1478 free((char *)old_shares);
1479 return(ret);
1482 /****************************************************************************
1483 C. Hoch 11/22/95
1484 Helper for open_file_shared.
1485 Truncate a file after checking locking; close file if locked.
1486 **************************************************************************/
1487 static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
1488 BOOL *share_locked)
1490 if (Files[fnum].can_write){
1491 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1492 /* If share modes are in force for this connection we
1493 have the share entry locked. Unlock it before closing. */
1494 if (*share_locked && lp_share_modes(SNUM(cnum)))
1495 unlock_share_entry( cnum, Files[fnum].fd_ptr->dev,
1496 Files[fnum].fd_ptr->inode, token);
1497 close_file(fnum);
1498 /* Share mode no longer locked. */
1499 *share_locked = False;
1500 errno = EACCES;
1501 unix_ERR_class = ERRDOS;
1502 unix_ERR_code = ERRlock;
1504 else
1505 ftruncate(Files[fnum].fd_ptr->fd,0);
1510 /****************************************************************************
1511 open a file with a share mode
1512 ****************************************************************************/
1513 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1514 int mode,int *Access,int *action)
1516 files_struct *fs_p = &Files[fnum];
1517 int flags=0;
1518 int flags2=0;
1519 int deny_mode = (share_mode>>4)&7;
1520 struct stat sbuf;
1521 BOOL file_existed = file_exist(fname,&sbuf);
1522 BOOL share_locked = False;
1523 BOOL fcbopen = False;
1524 share_lock_token token;
1525 uint32 dev = 0;
1526 uint32 inode = 0;
1528 fs_p->open = False;
1529 fs_p->fd_ptr = 0;
1531 /* this is for OS/2 EAs - try and say we don't support them */
1532 if (strstr(fname,".+,;=[]."))
1534 unix_ERR_class = ERRDOS;
1535 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1536 return;
1539 if ((ofun & 0x3) == 0 && file_existed)
1541 errno = EEXIST;
1542 return;
1545 if (ofun & 0x10)
1546 flags2 |= O_CREAT;
1547 if ((ofun & 0x3) == 2)
1548 flags2 |= O_TRUNC;
1550 /* note that we ignore the append flag as
1551 append does not mean the same thing under dos and unix */
1553 switch (share_mode&0xF)
1555 case 1:
1556 flags = O_WRONLY;
1557 break;
1558 case 0xF:
1559 fcbopen = True;
1560 flags = O_RDWR;
1561 break;
1562 case 2:
1563 flags = O_RDWR;
1564 break;
1565 default:
1566 flags = O_RDONLY;
1567 break;
1570 if (flags != O_RDONLY && file_existed &&
1571 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf))))
1573 if (!fcbopen)
1575 errno = EACCES;
1576 return;
1578 flags = O_RDONLY;
1581 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB)
1583 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1584 errno = EINVAL;
1585 return;
1588 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1590 if (lp_share_modes(SNUM(cnum)))
1592 int num_shares = 0;
1593 int i;
1594 min_share_mode_entry *old_shares = 0;
1597 if (file_existed)
1599 dev = (uint32)sbuf.st_dev;
1600 inode = (uint32)sbuf.st_ino;
1601 lock_share_entry(cnum, dev, inode, &token);
1602 share_locked = True;
1603 num_shares = get_share_modes(cnum, token, dev, inode, &old_shares);
1606 for(i = 0; i < num_shares; i++)
1608 /* someone else has a share lock on it, check to see
1609 if we can too */
1610 int old_open_mode = old_shares[i].share_mode &0xF;
1611 int old_deny_mode = (old_shares[i].share_mode >>4)&7;
1613 if (old_deny_mode > 4 || old_open_mode > 2)
1615 DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
1616 deny_mode,old_deny_mode,old_open_mode,fname));
1617 free((char *)old_shares);
1618 if(share_locked)
1619 unlock_share_entry(cnum, dev, inode, token);
1620 errno = EACCES;
1621 unix_ERR_class = ERRDOS;
1622 unix_ERR_code = ERRbadshare;
1623 return;
1627 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1628 old_shares[i].pid,fname);
1630 if ((access_allowed == AFAIL) ||
1631 (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
1632 (access_allowed == AREAD && flags == O_WRONLY) ||
1633 (access_allowed == AWRITE && flags == O_RDONLY))
1635 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1636 deny_mode,old_deny_mode,old_open_mode,
1637 old_shares[i].pid,fname,
1638 access_allowed));
1639 free((char *)old_shares);
1640 if(share_locked)
1641 unlock_share_entry(cnum, dev, inode, token);
1642 errno = EACCES;
1643 unix_ERR_class = ERRDOS;
1644 unix_ERR_code = ERRbadshare;
1645 return;
1648 if (access_allowed == AREAD)
1649 flags = O_RDONLY;
1651 if (access_allowed == AWRITE)
1652 flags = O_WRONLY;
1655 if(old_shares != 0)
1656 free((char *)old_shares);
1659 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1660 flags,flags2,mode));
1662 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1663 if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
1665 flags = O_RDONLY;
1666 open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1669 if (fs_p->open)
1671 int open_mode=0;
1673 if((share_locked == False) && lp_share_modes(SNUM(cnum)))
1675 /* We created the file - thus we must now lock the share entry before creating it. */
1676 dev = fs_p->fd_ptr->dev;
1677 inode = fs_p->fd_ptr->inode;
1678 lock_share_entry(cnum, dev, inode, &token);
1679 share_locked = True;
1682 switch (flags)
1684 case O_RDONLY:
1685 open_mode = 0;
1686 break;
1687 case O_RDWR:
1688 open_mode = 2;
1689 break;
1690 case O_WRONLY:
1691 open_mode = 1;
1692 break;
1695 fs_p->share_mode = (deny_mode<<4) | open_mode;
1697 if (Access)
1698 (*Access) = open_mode;
1700 if (action)
1702 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1703 if (!file_existed) *action = 2;
1704 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1706 /* We must create the share mode entry before truncate as
1707 truncate can fail due to locking and have to close the
1708 file (which expects the share_mode_entry to be there).
1710 if (lp_share_modes(SNUM(cnum)))
1711 set_share_mode(token, fnum);
1713 if ((flags2&O_TRUNC) && file_existed)
1714 truncate_unless_locked(fnum,cnum,token,&share_locked);
1717 if (share_locked && lp_share_modes(SNUM(cnum)))
1718 unlock_share_entry( cnum, dev, inode, token);
1721 /****************************************************************************
1722 seek a file. Try to avoid the seek if possible
1723 ****************************************************************************/
1724 int seek_file(int fnum,uint32 pos)
1726 uint32 offset = 0;
1727 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1728 offset = 3;
1730 Files[fnum].pos = (int)(lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET)
1731 - offset);
1732 return(Files[fnum].pos);
1735 /****************************************************************************
1736 read from a file
1737 ****************************************************************************/
1738 int read_file(int fnum,char *data,uint32 pos,int n)
1740 int ret=0,readret;
1742 if (!Files[fnum].can_write)
1744 ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1746 data += ret;
1747 n -= ret;
1748 pos += ret;
1751 #if USE_MMAP
1752 if (Files[fnum].mmap_ptr)
1754 int num = MIN(n,(int)(Files[fnum].mmap_size-pos));
1755 if (num > 0)
1757 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1758 data += num;
1759 pos += num;
1760 n -= num;
1761 ret += num;
1764 #endif
1766 if (n <= 0)
1767 return(ret);
1769 if (seek_file(fnum,pos) != pos)
1771 DEBUG(3,("Failed to seek to %d\n",pos));
1772 return(ret);
1775 if (n > 0) {
1776 readret = read(Files[fnum].fd_ptr->fd,data,n);
1777 if (readret > 0) ret += readret;
1780 return(ret);
1784 /****************************************************************************
1785 write to a file
1786 ****************************************************************************/
1787 int write_file(int fnum,char *data,int n)
1789 if (!Files[fnum].can_write) {
1790 errno = EPERM;
1791 return(0);
1794 if (!Files[fnum].modified) {
1795 struct stat st;
1796 Files[fnum].modified = True;
1797 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1798 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1799 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1800 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1805 return(write_data(Files[fnum].fd_ptr->fd,data,n));
1809 /****************************************************************************
1810 load parameters specific to a connection/service
1811 ****************************************************************************/
1812 BOOL become_service(int cnum,BOOL do_chdir)
1814 extern char magic_char;
1815 static int last_cnum = -1;
1816 int snum;
1818 if (!OPEN_CNUM(cnum))
1820 last_cnum = -1;
1821 return(False);
1824 Connections[cnum].lastused = smb_last_time;
1826 snum = SNUM(cnum);
1828 if (do_chdir &&
1829 ChDir(Connections[cnum].connectpath) != 0 &&
1830 ChDir(Connections[cnum].origpath) != 0)
1832 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1833 Connections[cnum].connectpath,cnum));
1834 return(False);
1837 if (cnum == last_cnum)
1838 return(True);
1840 last_cnum = cnum;
1842 case_default = lp_defaultcase(snum);
1843 case_preserve = lp_preservecase(snum);
1844 short_case_preserve = lp_shortpreservecase(snum);
1845 case_mangle = lp_casemangle(snum);
1846 case_sensitive = lp_casesensitive(snum);
1847 magic_char = lp_magicchar(snum);
1848 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1849 return(True);
1853 /****************************************************************************
1854 find a service entry
1855 ****************************************************************************/
1856 int find_service(char *service)
1858 int iService;
1860 string_sub(service,"\\","/");
1862 iService = lp_servicenumber(service);
1864 /* now handle the special case of a home directory */
1865 if (iService < 0)
1867 char *phome_dir = get_home_dir(service);
1868 DEBUG(3,("checking for home directory %s gave %s\n",service,
1869 phome_dir?phome_dir:"(NULL)"));
1870 if (phome_dir)
1872 int iHomeService;
1873 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1875 lp_add_home(service,iHomeService,phome_dir);
1876 iService = lp_servicenumber(service);
1881 /* If we still don't have a service, attempt to add it as a printer. */
1882 if (iService < 0)
1884 int iPrinterService;
1886 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1888 char *pszTemp;
1890 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1891 pszTemp = PRINTCAP;
1892 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1894 DEBUG(3,("%s is a valid printer name\n", service));
1895 DEBUG(3,("adding %s as a printer service\n", service));
1896 lp_add_printer(service,iPrinterService);
1897 iService = lp_servicenumber(service);
1898 if (iService < 0)
1899 DEBUG(0,("failed to add %s as a printer service!\n", service));
1901 else
1902 DEBUG(3,("%s is not a valid printer name\n", service));
1906 /* just possibly it's a default service? */
1907 if (iService < 0)
1909 char *defservice = lp_defaultservice();
1910 if (defservice && *defservice && !strequal(defservice,service)) {
1911 iService = find_service(defservice);
1912 if (iService >= 0) {
1913 string_sub(service,"_","/");
1914 iService = lp_add_service(service,iService);
1919 if (iService >= 0)
1920 if (!VALID_SNUM(iService))
1922 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1923 iService = -1;
1926 if (iService < 0)
1927 DEBUG(3,("find_service() failed to find service %s\n", service));
1929 return (iService);
1933 /****************************************************************************
1934 create an error packet from a cached error.
1935 ****************************************************************************/
1936 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1938 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1940 int32 eclass = wbmpx->wr_errclass;
1941 int32 err = wbmpx->wr_error;
1943 /* We can now delete the auxiliary struct */
1944 free((char *)wbmpx);
1945 Files[fnum].wbmpx_ptr = NULL;
1946 return error_packet(inbuf,outbuf,eclass,err,line);
1950 struct
1952 int unixerror;
1953 int smbclass;
1954 int smbcode;
1955 } unix_smb_errmap[] =
1957 {EPERM,ERRDOS,ERRnoaccess},
1958 {EACCES,ERRDOS,ERRnoaccess},
1959 {ENOENT,ERRDOS,ERRbadfile},
1960 {ENOTDIR,ERRDOS,ERRbaddirectory},
1961 {EIO,ERRHRD,ERRgeneral},
1962 {EBADF,ERRSRV,ERRsrverror},
1963 {EINVAL,ERRSRV,ERRsrverror},
1964 {EEXIST,ERRDOS,ERRfilexists},
1965 {ENFILE,ERRDOS,ERRnofids},
1966 {EMFILE,ERRDOS,ERRnofids},
1967 {ENOSPC,ERRHRD,ERRdiskfull},
1968 #ifdef EDQUOT
1969 {EDQUOT,ERRHRD,ERRdiskfull},
1970 #endif
1971 #ifdef ENOTEMPTY
1972 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1973 #endif
1974 #ifdef EXDEV
1975 {EXDEV,ERRDOS,ERRdiffdevice},
1976 #endif
1977 {EROFS,ERRHRD,ERRnowrite},
1978 {0,0,0}
1982 /****************************************************************************
1983 create an error packet from errno
1984 ****************************************************************************/
1985 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1987 int eclass=def_class;
1988 int ecode=def_code;
1989 int i=0;
1991 if (unix_ERR_class != SUCCESS)
1993 eclass = unix_ERR_class;
1994 ecode = unix_ERR_code;
1995 unix_ERR_class = SUCCESS;
1996 unix_ERR_code = 0;
1998 else
2000 while (unix_smb_errmap[i].smbclass != 0)
2002 if (unix_smb_errmap[i].unixerror == errno)
2004 eclass = unix_smb_errmap[i].smbclass;
2005 ecode = unix_smb_errmap[i].smbcode;
2006 break;
2008 i++;
2012 return(error_packet(inbuf,outbuf,eclass,ecode,line));
2016 /****************************************************************************
2017 create an error packet. Normally called using the ERROR() macro
2018 ****************************************************************************/
2019 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
2021 int outsize = set_message(outbuf,0,0,True);
2022 int cmd;
2023 cmd = CVAL(inbuf,smb_com);
2025 CVAL(outbuf,smb_rcls) = error_class;
2026 SSVAL(outbuf,smb_err,error_code);
2028 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
2029 timestring(),
2030 line,
2031 (int)CVAL(inbuf,smb_com),
2032 smb_fn_name(CVAL(inbuf,smb_com)),
2033 error_class,
2034 error_code));
2036 if (errno != 0)
2037 DEBUG(3,("error string = %s\n",strerror(errno)));
2039 return(outsize);
2043 #ifndef SIGCLD_IGNORE
2044 /****************************************************************************
2045 this prevents zombie child processes
2046 ****************************************************************************/
2047 static int sig_cld()
2049 static int depth = 0;
2050 if (depth != 0)
2052 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2053 depth=0;
2054 return(0);
2056 depth++;
2058 BlockSignals(True,SIGCLD);
2059 DEBUG(5,("got SIGCLD\n"));
2061 #ifdef USE_WAITPID
2062 while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2063 #endif
2065 /* Stop zombies */
2066 /* Stevens, Adv. Unix Prog. says that on system V you must call
2067 wait before reinstalling the signal handler, because the kernel
2068 calls the handler from within the signal-call when there is a
2069 child that has exited. This would lead to an infinite recursion
2070 if done vice versa. */
2072 #ifndef DONT_REINSTALL_SIG
2073 #ifdef SIGCLD_IGNORE
2074 signal(SIGCLD, SIG_IGN);
2075 #else
2076 signal(SIGCLD, SIGNAL_CAST sig_cld);
2077 #endif
2078 #endif
2080 #ifndef USE_WAITPID
2081 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
2082 #endif
2083 depth--;
2084 BlockSignals(False,SIGCLD);
2085 return 0;
2087 #endif
2089 /****************************************************************************
2090 this is called when the client exits abruptly
2091 **************************************************************************/
2092 static int sig_pipe()
2094 extern int password_client;
2095 BlockSignals(True,SIGPIPE);
2097 if (password_client != -1) {
2098 DEBUG(3,("lost connection to password server\n"));
2099 close(password_client);
2100 password_client = -1;
2101 #ifndef DONT_REINSTALL_SIG
2102 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2103 #endif
2104 BlockSignals(False,SIGPIPE);
2105 return 0;
2108 exit_server("Got sigpipe\n");
2109 return(0);
2112 /****************************************************************************
2113 open the socket communication
2114 ****************************************************************************/
2115 static BOOL open_sockets(BOOL is_daemon,int port)
2117 extern int Client;
2119 if (is_daemon)
2121 int s;
2122 struct sockaddr addr;
2123 int in_addrlen = sizeof(addr);
2125 /* Stop zombies */
2126 #ifdef SIGCLD_IGNORE
2127 signal(SIGCLD, SIG_IGN);
2128 #else
2129 signal(SIGCLD, SIGNAL_CAST sig_cld);
2130 #endif
2132 /* open an incoming socket */
2133 s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
2134 if (s == -1)
2135 return(False);
2137 /* ready to listen */
2138 if (listen(s, 5) == -1)
2140 DEBUG(0,("listen: %s\n",strerror(errno)));
2141 close(s);
2142 return False;
2145 if(atexit_set == 0)
2146 atexit(killkids);
2148 /* now accept incoming connections - forking a new process
2149 for each incoming connection */
2150 DEBUG(2,("waiting for a connection\n"));
2151 while (1)
2153 Client = accept(s,&addr,&in_addrlen);
2155 if (Client == -1 && errno == EINTR)
2156 continue;
2158 if (Client == -1)
2160 DEBUG(0,("accept: %s\n",strerror(errno)));
2161 continue;
2164 #ifdef NO_FORK_DEBUG
2165 #ifndef NO_SIGNAL_TEST
2166 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2167 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2168 #endif
2169 return True;
2170 #else
2171 if (Client != -1 && fork()==0)
2173 /* Child code ... */
2174 #ifndef NO_SIGNAL_TEST
2175 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2176 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2177 #endif
2178 /* close the listening socket */
2179 close(s);
2181 /* close our standard file descriptors */
2182 close_low_fds();
2183 am_parent = 0;
2185 set_socket_options(Client,"SO_KEEPALIVE");
2186 set_socket_options(Client,user_socket_options);
2188 /* Reset global variables in util.c so that
2189 client substitutions will be done correctly
2190 in the process.
2192 reset_globals_after_fork();
2193 return True;
2195 close(Client); /* The parent doesn't need this socket */
2196 #endif
2199 else
2201 /* We will abort gracefully when the client or remote system
2202 goes away */
2203 #ifndef NO_SIGNAL_TEST
2204 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2205 #endif
2206 Client = dup(0);
2208 /* close our standard file descriptors */
2209 close_low_fds();
2211 set_socket_options(Client,"SO_KEEPALIVE");
2212 set_socket_options(Client,user_socket_options);
2215 return True;
2219 /****************************************************************************
2220 check if a snum is in use
2221 ****************************************************************************/
2222 BOOL snum_used(int snum)
2224 int i;
2225 for (i=0;i<MAX_CONNECTIONS;i++)
2226 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2227 return(True);
2228 return(False);
2231 /****************************************************************************
2232 reload the services file
2233 **************************************************************************/
2234 BOOL reload_services(BOOL test)
2236 BOOL ret;
2238 if (lp_loaded())
2240 pstring fname;
2241 strcpy(fname,lp_configfile());
2242 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2244 strcpy(servicesf,fname);
2245 test = False;
2249 reopen_logs();
2251 if (test && !lp_file_list_changed())
2252 return(True);
2254 lp_killunused(snum_used);
2256 ret = lp_load(servicesf,False);
2258 /* perhaps the config filename is now set */
2259 if (!test)
2260 reload_services(True);
2262 reopen_logs();
2264 load_interfaces();
2267 extern int Client;
2268 if (Client != -1) {
2269 set_socket_options(Client,"SO_KEEPALIVE");
2270 set_socket_options(Client,user_socket_options);
2274 create_mangled_stack(lp_mangledstack());
2276 /* this forces service parameters to be flushed */
2277 become_service(-1,True);
2279 return(ret);
2284 /****************************************************************************
2285 this prevents zombie child processes
2286 ****************************************************************************/
2287 static int sig_hup()
2289 BlockSignals(True,SIGHUP);
2290 DEBUG(0,("Got SIGHUP\n"));
2291 reload_services(False);
2292 #ifndef DONT_REINSTALL_SIG
2293 signal(SIGHUP,SIGNAL_CAST sig_hup);
2294 #endif
2295 BlockSignals(False,SIGHUP);
2296 return(0);
2299 /****************************************************************************
2300 Setup the groups a user belongs to.
2301 ****************************************************************************/
2302 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
2303 int **p_igroups, gid_t **p_groups)
2305 if (-1 == initgroups(user,gid))
2307 if (getuid() == 0)
2309 DEBUG(0,("Unable to initgroups!\n"));
2310 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2311 DEBUG(0,("This is probably a problem with the account %s\n",user));
2314 else
2316 int i,ngroups;
2317 int *igroups;
2318 gid_t grp = 0;
2319 ngroups = getgroups(0,&grp);
2320 if (ngroups <= 0)
2321 ngroups = 32;
2322 igroups = (int *)malloc(sizeof(int)*ngroups);
2323 for (i=0;i<ngroups;i++)
2324 igroups[i] = 0x42424242;
2325 ngroups = getgroups(ngroups,(gid_t *)igroups);
2327 if (igroups[0] == 0x42424242)
2328 ngroups = 0;
2330 *p_ngroups = ngroups;
2332 /* The following bit of code is very strange. It is due to the
2333 fact that some OSes use int* and some use gid_t* for
2334 getgroups, and some (like SunOS) use both, one in prototypes,
2335 and one in man pages and the actual code. Thus we detect it
2336 dynamically using some very ugly code */
2337 if (ngroups > 0)
2339 /* does getgroups return ints or gid_t ?? */
2340 static BOOL groups_use_ints = True;
2342 if (groups_use_ints &&
2343 ngroups == 1 &&
2344 SVAL(igroups,2) == 0x4242)
2345 groups_use_ints = False;
2347 for (i=0;groups_use_ints && i<ngroups;i++)
2348 if (igroups[i] == 0x42424242)
2349 groups_use_ints = False;
2351 if (groups_use_ints)
2353 *p_igroups = igroups;
2354 *p_groups = (gid_t *)igroups;
2356 else
2358 gid_t *groups = (gid_t *)igroups;
2359 igroups = (int *)malloc(sizeof(int)*ngroups);
2360 for (i=0;i<ngroups;i++)
2361 igroups[i] = groups[i];
2362 *p_igroups = igroups;
2363 *p_groups = (gid_t *)groups;
2366 DEBUG(3,("%s is in %d groups\n",user,ngroups));
2367 for (i=0;i<ngroups;i++)
2368 DEBUG(3,("%d ",igroups[i]));
2369 DEBUG(3,("\n"));
2371 return 0;
2374 /****************************************************************************
2375 make a connection to a service
2376 ****************************************************************************/
2377 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2379 int cnum;
2380 int snum;
2381 struct passwd *pass = NULL;
2382 connection_struct *pcon;
2383 BOOL guest = False;
2384 BOOL force = False;
2385 static BOOL first_connection = True;
2387 strlower(service);
2389 snum = find_service(service);
2390 if (snum < 0)
2392 if (strequal(service,"IPC$"))
2394 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2395 return(-3);
2398 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2399 return(-2);
2402 if (strequal(service,HOMES_NAME))
2404 if (*user && Get_Pwnam(user,True))
2405 return(make_connection(user,user,password,pwlen,dev,vuid));
2407 if (validated_username(vuid))
2409 strcpy(user,validated_username(vuid));
2410 return(make_connection(user,user,password,pwlen,dev,vuid));
2414 if (!lp_snum_ok(snum) || !check_access(snum)) {
2415 return(-4);
2418 /* you can only connect to the IPC$ service as an ipc device */
2419 if (strequal(service,"IPC$"))
2420 strcpy(dev,"IPC");
2422 if (*dev == '?' || !*dev)
2424 if (lp_print_ok(snum))
2425 strcpy(dev,"LPT1:");
2426 else
2427 strcpy(dev,"A:");
2430 /* if the request is as a printer and you can't print then refuse */
2431 strupper(dev);
2432 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2433 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2434 return(-6);
2437 /* lowercase the user name */
2438 strlower(user);
2440 /* add it as a possible user name */
2441 add_session_user(service);
2443 /* shall we let them in? */
2444 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2446 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2447 return(-1);
2450 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2451 if (cnum < 0)
2453 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2454 return(-1);
2457 pcon = &Connections[cnum];
2458 bzero((char *)pcon,sizeof(*pcon));
2460 /* find out some info about the user */
2461 pass = Get_Pwnam(user,True);
2463 if (pass == NULL)
2465 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2466 return(-7);
2469 pcon->read_only = lp_readonly(snum);
2472 pstring list;
2473 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2474 string_sub(list,"%S",service);
2476 if (user_in_list(user,list))
2477 pcon->read_only = True;
2479 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2480 string_sub(list,"%S",service);
2482 if (user_in_list(user,list))
2483 pcon->read_only = False;
2486 /* admin user check */
2487 if (user_in_list(user,lp_admin_users(snum)) &&
2488 !pcon->read_only)
2490 pcon->admin_user = True;
2491 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2493 else
2494 pcon->admin_user = False;
2496 pcon->force_user = force;
2497 pcon->vuid = vuid;
2498 pcon->uid = pass->pw_uid;
2499 pcon->gid = pass->pw_gid;
2500 pcon->num_files_open = 0;
2501 pcon->lastused = time(NULL);
2502 pcon->service = snum;
2503 pcon->used = True;
2504 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2505 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2506 pcon->dirptr = NULL;
2507 pcon->veto_list = NULL;
2508 pcon->hide_list = NULL;
2509 string_set(&pcon->dirpath,"");
2510 string_set(&pcon->user,user);
2512 #if HAVE_GETGRNAM
2513 if (*lp_force_group(snum))
2515 struct group *gptr;
2516 pstring gname;
2518 StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2519 /* default service may be a group name */
2520 string_sub(gname,"%S",service);
2521 gptr = (struct group *)getgrnam(gname);
2523 if (gptr)
2525 pcon->gid = gptr->gr_gid;
2526 DEBUG(3,("Forced group %s\n",gname));
2528 else
2529 DEBUG(1,("Couldn't find group %s\n",gname));
2531 #endif
2533 if (*lp_force_user(snum))
2535 struct passwd *pass2;
2536 fstring fuser;
2537 strcpy(fuser,lp_force_user(snum));
2538 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2539 if (pass2)
2541 pcon->uid = pass2->pw_uid;
2542 string_set(&pcon->user,fuser);
2543 strcpy(user,fuser);
2544 pcon->force_user = True;
2545 DEBUG(3,("Forced user %s\n",fuser));
2547 else
2548 DEBUG(1,("Couldn't find user %s\n",fuser));
2552 pstring s;
2553 strcpy(s,lp_pathname(snum));
2554 standard_sub(cnum,s);
2555 string_set(&pcon->connectpath,s);
2556 DEBUG(3,("Connect path is %s\n",s));
2559 /* groups stuff added by ih */
2560 pcon->ngroups = 0;
2561 pcon->groups = NULL;
2563 if (!IS_IPC(cnum))
2565 /* Find all the groups this uid is in and store them. Used by become_user() */
2566 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2568 /* check number of connections */
2569 if (!claim_connection(cnum,
2570 lp_servicename(SNUM(cnum)),
2571 lp_max_connections(SNUM(cnum)),False))
2573 DEBUG(1,("too many connections - rejected\n"));
2574 return(-8);
2577 if (lp_status(SNUM(cnum)))
2578 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2580 first_connection = False;
2581 } /* IS_IPC */
2583 pcon->open = True;
2585 /* execute any "root preexec = " line */
2586 if (*lp_rootpreexec(SNUM(cnum)))
2588 pstring cmd;
2589 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2590 standard_sub(cnum,cmd);
2591 DEBUG(5,("cmd=%s\n",cmd));
2592 smbrun(cmd,NULL,False);
2595 if (!become_user(cnum,pcon->vuid))
2597 DEBUG(0,("Can't become connected user!\n"));
2598 pcon->open = False;
2599 if (!IS_IPC(cnum)) {
2600 yield_connection(cnum,
2601 lp_servicename(SNUM(cnum)),
2602 lp_max_connections(SNUM(cnum)));
2603 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2605 return(-1);
2608 if (ChDir(pcon->connectpath) != 0)
2610 DEBUG(0,("Can't change directory to %s (%s)\n",
2611 pcon->connectpath,strerror(errno)));
2612 pcon->open = False;
2613 unbecome_user();
2614 if (!IS_IPC(cnum)) {
2615 yield_connection(cnum,
2616 lp_servicename(SNUM(cnum)),
2617 lp_max_connections(SNUM(cnum)));
2618 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2620 return(-5);
2623 string_set(&pcon->origpath,pcon->connectpath);
2625 #if SOFTLINK_OPTIMISATION
2626 /* resolve any soft links early */
2628 pstring s;
2629 strcpy(s,pcon->connectpath);
2630 GetWd(s);
2631 string_set(&pcon->connectpath,s);
2632 ChDir(pcon->connectpath);
2634 #endif
2636 num_connections_open++;
2637 add_session_user(user);
2639 /* execute any "preexec = " line */
2640 if (*lp_preexec(SNUM(cnum)))
2642 pstring cmd;
2643 strcpy(cmd,lp_preexec(SNUM(cnum)));
2644 standard_sub(cnum,cmd);
2645 smbrun(cmd,NULL,False);
2648 /* we've finished with the sensitive stuff */
2649 unbecome_user();
2651 /* Add veto/hide lists */
2652 if (!IS_IPC(cnum) && !IS_PRINT(cnum))
2654 set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum)));
2655 set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum)));
2659 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2660 timestring(),
2661 remote_machine,
2662 client_addr(),
2663 lp_servicename(SNUM(cnum)),user,
2664 pcon->uid,
2665 pcon->gid,
2666 (int)getpid()));
2669 return(cnum);
2673 /****************************************************************************
2674 find first available file slot
2675 ****************************************************************************/
2676 int find_free_file(void )
2678 int i;
2679 /* we start at 1 here for an obscure reason I can't now remember,
2680 but I think is important :-) */
2681 for (i=1;i<MAX_OPEN_FILES;i++)
2682 if (!Files[i].open)
2683 return(i);
2684 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2685 return(-1);
2688 /****************************************************************************
2689 find first available connection slot, starting from a random position.
2690 The randomisation stops problems with the server dieing and clients
2691 thinking the server is still available.
2692 ****************************************************************************/
2693 static int find_free_connection(int hash )
2695 int i;
2696 BOOL used=False;
2697 hash = (hash % (MAX_CONNECTIONS-2))+1;
2699 again:
2701 for (i=hash+1;i!=hash;)
2703 if (!Connections[i].open && Connections[i].used == used)
2705 DEBUG(3,("found free connection number %d\n",i));
2706 return(i);
2708 i++;
2709 if (i == MAX_CONNECTIONS)
2710 i = 1;
2713 if (!used)
2715 used = !used;
2716 goto again;
2719 DEBUG(1,("ERROR! Out of connection structures\n"));
2720 return(-1);
2724 /****************************************************************************
2725 reply for the core protocol
2726 ****************************************************************************/
2727 int reply_corep(char *outbuf)
2729 int outsize = set_message(outbuf,1,0,True);
2731 Protocol = PROTOCOL_CORE;
2733 return outsize;
2737 /****************************************************************************
2738 reply for the coreplus protocol
2739 ****************************************************************************/
2740 int reply_coreplus(char *outbuf)
2742 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2743 int outsize = set_message(outbuf,13,0,True);
2744 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2745 readbraw and writebraw (possibly) */
2746 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2747 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2749 Protocol = PROTOCOL_COREPLUS;
2751 return outsize;
2755 /****************************************************************************
2756 reply for the lanman 1.0 protocol
2757 ****************************************************************************/
2758 int reply_lanman1(char *outbuf)
2760 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2761 int secword=0;
2762 BOOL doencrypt = SMBENCRYPT();
2763 time_t t = time(NULL);
2764 /* We need to save and restore this as it can be destroyed
2765 if we call another server if security=server
2766 Thanks to Paul Nelson @ Thursby for pointing this out.
2768 uint16 mid = SVAL(outbuf, smb_mid);
2770 if (lp_security()>=SEC_USER) secword |= 1;
2771 if (doencrypt) secword |= 2;
2773 set_message(outbuf,13,doencrypt?8:0,True);
2774 SSVAL(outbuf,smb_vwv1,secword);
2775 #ifdef SMB_PASSWD
2776 /* Create a token value and add it to the outgoing packet. */
2777 if (doencrypt)
2778 generate_next_challenge(smb_buf(outbuf));
2779 #endif
2781 Protocol = PROTOCOL_LANMAN1;
2783 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2784 DEBUG(3,("using password server validation\n"));
2785 #ifdef SMB_PASSWD
2786 if (doencrypt) set_challenge(smb_buf(outbuf));
2787 #endif
2790 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2791 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2792 SSVAL(outbuf,smb_vwv2,max_recv);
2793 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2794 SSVAL(outbuf,smb_vwv4,1);
2795 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2796 readbraw writebraw (possibly) */
2797 SIVAL(outbuf,smb_vwv6,getpid());
2798 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2800 put_dos_date(outbuf,smb_vwv8,t);
2802 return (smb_len(outbuf)+4);
2806 /****************************************************************************
2807 reply for the lanman 2.0 protocol
2808 ****************************************************************************/
2809 int reply_lanman2(char *outbuf)
2811 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2812 int secword=0;
2813 BOOL doencrypt = SMBENCRYPT();
2814 time_t t = time(NULL);
2815 /* We need to save and restore this as it can be destroyed
2816 if we call another server if security=server
2817 Thanks to Paul Nelson @ Thursby for pointing this out.
2819 uint16 mid = SVAL(outbuf, smb_mid);
2821 if (lp_security()>=SEC_USER) secword |= 1;
2822 if (doencrypt) secword |= 2;
2824 set_message(outbuf,13,doencrypt?8:0,True);
2825 SSVAL(outbuf,smb_vwv1,secword);
2826 #ifdef SMB_PASSWD
2827 /* Create a token value and add it to the outgoing packet. */
2828 if (doencrypt)
2829 generate_next_challenge(smb_buf(outbuf));
2830 #endif
2832 SIVAL(outbuf,smb_vwv6,getpid());
2834 Protocol = PROTOCOL_LANMAN2;
2836 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2837 DEBUG(3,("using password server validation\n"));
2838 #ifdef SMB_PASSWD
2839 if (doencrypt) set_challenge(smb_buf(outbuf));
2840 #endif
2843 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2844 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2845 SSVAL(outbuf,smb_vwv2,max_recv);
2846 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2847 SSVAL(outbuf,smb_vwv4,1);
2848 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2849 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2850 put_dos_date(outbuf,smb_vwv8,t);
2852 return (smb_len(outbuf)+4);
2856 /****************************************************************************
2857 reply for the nt protocol
2858 ****************************************************************************/
2859 int reply_nt1(char *outbuf)
2861 /* dual names + lock_and_read + nt SMBs + remote API calls */
2862 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
2864 other valid capabilities which we may support at some time...
2865 CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
2866 CAP_LARGE_FILES|CAP_LARGE_READX|
2867 CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
2870 int secword=0;
2871 BOOL doencrypt = SMBENCRYPT();
2872 time_t t = time(NULL);
2873 int data_len;
2874 int encrypt_len;
2875 char challenge_len = 8;
2876 /* We need to save and restore this as it can be destroyed
2877 if we call another server if security=server
2878 Thanks to Paul Nelson @ Thursby for pointing this out.
2880 uint16 mid = SVAL(outbuf, smb_mid);
2882 if (lp_readraw() && lp_writeraw())
2884 capabilities |= CAP_RAW_MODE;
2887 if (lp_security()>=SEC_USER) secword |= 1;
2888 if (doencrypt) secword |= 2;
2890 /* decide where (if) to put the encryption challenge, and
2891 follow it with the OEM'd domain name
2893 encrypt_len = doencrypt?challenge_len:0;
2894 #if UNICODE
2895 data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
2896 #else
2897 data_len = encrypt_len + strlen(myworkgroup) + 1;
2898 #endif
2900 set_message(outbuf,17,data_len,True);
2902 #if UNICODE
2903 /* put the OEM'd domain name */
2904 PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
2905 #else
2906 strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
2907 #endif
2909 CVAL(outbuf,smb_vwv1) = secword;
2910 #ifdef SMB_PASSWD
2911 /* Create a token value and add it to the outgoing packet. */
2912 if (doencrypt)
2914 generate_next_challenge(smb_buf(outbuf));
2916 /* Tell the nt machine how long the challenge is. */
2917 SSVALS(outbuf,smb_vwv16+1,challenge_len);
2919 #endif
2921 Protocol = PROTOCOL_NT1;
2923 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2924 DEBUG(3,("using password server validation\n"));
2925 #ifdef SMB_PASSWD
2926 if (doencrypt) set_challenge(smb_buf(outbuf));
2927 #endif
2930 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2931 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2932 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2933 SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
2934 SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
2935 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2936 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2937 put_long_date(outbuf+smb_vwv11+1,t);
2938 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2939 SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
2941 return (smb_len(outbuf)+4);
2944 /* these are the protocol lists used for auto architecture detection:
2946 WinNT 3.51:
2947 protocol [PC NETWORK PROGRAM 1.0]
2948 protocol [XENIX CORE]
2949 protocol [MICROSOFT NETWORKS 1.03]
2950 protocol [LANMAN1.0]
2951 protocol [Windows for Workgroups 3.1a]
2952 protocol [LM1.2X002]
2953 protocol [LANMAN2.1]
2954 protocol [NT LM 0.12]
2956 Win95:
2957 protocol [PC NETWORK PROGRAM 1.0]
2958 protocol [XENIX CORE]
2959 protocol [MICROSOFT NETWORKS 1.03]
2960 protocol [LANMAN1.0]
2961 protocol [Windows for Workgroups 3.1a]
2962 protocol [LM1.2X002]
2963 protocol [LANMAN2.1]
2964 protocol [NT LM 0.12]
2966 OS/2:
2967 protocol [PC NETWORK PROGRAM 1.0]
2968 protocol [XENIX CORE]
2969 protocol [LANMAN1.0]
2970 protocol [LM1.2X002]
2971 protocol [LANMAN2.1]
2975 * Modified to recognize the architecture of the remote machine better.
2977 * This appears to be the matrix of which protocol is used by which
2978 * MS product.
2979 Protocol WfWg Win95 WinNT OS/2
2980 PC NETWORK PROGRAM 1.0 1 1 1 1
2981 XENIX CORE 2 2
2982 MICROSOFT NETWORKS 3.0 2 2
2983 DOS LM1.2X002 3 3
2984 MICROSOFT NETWORKS 1.03 3
2985 DOS LANMAN2.1 4 4
2986 LANMAN1.0 4 3
2987 Windows for Workgroups 3.1a 5 5 5
2988 LM1.2X002 6 4
2989 LANMAN2.1 7 5
2990 NT LM 0.12 6 8
2992 * tim@fsg.com 09/29/95
2995 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2996 #define ARCH_WIN95 0x2
2997 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2998 #define ARCH_WINNT 0x8
2999 #define ARCH_SAMBA 0x10
3001 #define ARCH_ALL 0x1F
3003 /* List of supported protocols, most desired first */
3004 struct {
3005 char *proto_name;
3006 char *short_name;
3007 int (*proto_reply_fn)(char *);
3008 int protocol_level;
3009 } supported_protocols[] = {
3010 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
3011 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
3012 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
3013 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
3014 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
3015 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
3016 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
3017 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
3018 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
3019 {NULL,NULL},
3023 /****************************************************************************
3024 reply to a negprot
3025 ****************************************************************************/
3026 static int reply_negprot(char *inbuf,char *outbuf)
3028 extern fstring remote_arch;
3029 int outsize = set_message(outbuf,1,0,True);
3030 int Index=0;
3031 int choice= -1;
3032 int protocol;
3033 char *p;
3034 int bcc = SVAL(smb_buf(inbuf),-2);
3035 int arch = ARCH_ALL;
3037 p = smb_buf(inbuf)+1;
3038 while (p < (smb_buf(inbuf) + bcc))
3040 Index++;
3041 DEBUG(3,("Requested protocol [%s]\n",p));
3042 if (strcsequal(p,"Windows for Workgroups 3.1a"))
3043 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
3044 else if (strcsequal(p,"DOS LM1.2X002"))
3045 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3046 else if (strcsequal(p,"DOS LANMAN2.1"))
3047 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3048 else if (strcsequal(p,"NT LM 0.12"))
3049 arch &= ( ARCH_WIN95 | ARCH_WINNT );
3050 else if (strcsequal(p,"LANMAN2.1"))
3051 arch &= ( ARCH_WINNT | ARCH_OS2 );
3052 else if (strcsequal(p,"LM1.2X002"))
3053 arch &= ( ARCH_WINNT | ARCH_OS2 );
3054 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
3055 arch &= ARCH_WINNT;
3056 else if (strcsequal(p,"XENIX CORE"))
3057 arch &= ( ARCH_WINNT | ARCH_OS2 );
3058 else if (strcsequal(p,"Samba")) {
3059 arch = ARCH_SAMBA;
3060 break;
3063 p += strlen(p) + 2;
3066 switch ( arch ) {
3067 case ARCH_SAMBA:
3068 strcpy(remote_arch,"Samba");
3069 break;
3070 case ARCH_WFWG:
3071 strcpy(remote_arch,"WfWg");
3072 break;
3073 case ARCH_WIN95:
3074 strcpy(remote_arch,"Win95");
3075 break;
3076 case ARCH_WINNT:
3077 strcpy(remote_arch,"WinNT");
3078 break;
3079 case ARCH_OS2:
3080 strcpy(remote_arch,"OS2");
3081 break;
3082 default:
3083 strcpy(remote_arch,"UNKNOWN");
3084 break;
3087 /* possibly reload - change of architecture */
3088 reload_services(True);
3090 /* a special case to stop password server loops */
3091 if (Index == 1 && strequal(remote_machine,myhostname) &&
3092 lp_security()==SEC_SERVER)
3093 exit_server("Password server loop!");
3095 /* Check for protocols, most desirable first */
3096 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
3098 p = smb_buf(inbuf)+1;
3099 Index = 0;
3100 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
3101 while (p < (smb_buf(inbuf) + bcc))
3103 if (strequal(p,supported_protocols[protocol].proto_name))
3104 choice = Index;
3105 Index++;
3106 p += strlen(p) + 2;
3108 if(choice != -1)
3109 break;
3112 SSVAL(outbuf,smb_vwv0,choice);
3113 if(choice != -1) {
3114 extern fstring remote_proto;
3115 strcpy(remote_proto,supported_protocols[protocol].short_name);
3116 reload_services(True);
3117 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
3118 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
3120 else {
3121 DEBUG(0,("No protocol supported !\n"));
3123 SSVAL(outbuf,smb_vwv0,choice);
3125 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3127 return(outsize);
3131 /****************************************************************************
3132 close all open files for a connection
3133 ****************************************************************************/
3134 static void close_open_files(int cnum)
3136 int i;
3137 for (i=0;i<MAX_OPEN_FILES;i++)
3138 if( Files[i].cnum == cnum && Files[i].open) {
3139 close_file(i);
3145 /****************************************************************************
3146 close a cnum
3147 ****************************************************************************/
3148 void close_cnum(int cnum, uint16 vuid)
3150 DirCacheFlush(SNUM(cnum));
3152 unbecome_user();
3154 if (!OPEN_CNUM(cnum))
3156 DEBUG(0,("Can't close cnum %d\n",cnum));
3157 return;
3160 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3161 timestring(),
3162 remote_machine,client_addr(),
3163 lp_servicename(SNUM(cnum))));
3165 yield_connection(cnum,
3166 lp_servicename(SNUM(cnum)),
3167 lp_max_connections(SNUM(cnum)));
3169 if (lp_status(SNUM(cnum)))
3170 yield_connection(cnum,"STATUS.",MAXSTATUS);
3172 close_open_files(cnum);
3173 dptr_closecnum(cnum);
3175 /* execute any "postexec = " line */
3176 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
3178 pstring cmd;
3179 strcpy(cmd,lp_postexec(SNUM(cnum)));
3180 standard_sub(cnum,cmd);
3181 smbrun(cmd,NULL,False);
3182 unbecome_user();
3185 unbecome_user();
3186 /* execute any "root postexec = " line */
3187 if (*lp_rootpostexec(SNUM(cnum)))
3189 pstring cmd;
3190 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3191 standard_sub(cnum,cmd);
3192 smbrun(cmd,NULL,False);
3195 Connections[cnum].open = False;
3196 num_connections_open--;
3197 if (Connections[cnum].ngroups && Connections[cnum].groups)
3199 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3200 free(Connections[cnum].groups);
3201 free(Connections[cnum].igroups);
3202 Connections[cnum].groups = NULL;
3203 Connections[cnum].igroups = NULL;
3204 Connections[cnum].ngroups = 0;
3207 free_namearray(Connections[cnum].veto_list);
3208 free_namearray(Connections[cnum].hide_list);
3210 string_set(&Connections[cnum].user,"");
3211 string_set(&Connections[cnum].dirpath,"");
3212 string_set(&Connections[cnum].connectpath,"");
3216 /****************************************************************************
3217 simple routines to do connection counting
3218 ****************************************************************************/
3219 BOOL yield_connection(int cnum,char *name,int max_connections)
3221 struct connect_record crec;
3222 pstring fname;
3223 FILE *f;
3224 int mypid = getpid();
3225 int i;
3227 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3229 if (max_connections <= 0)
3230 return(True);
3232 bzero(&crec,sizeof(crec));
3234 strcpy(fname,lp_lockdir());
3235 standard_sub(cnum,fname);
3236 trim_string(fname,"","/");
3238 strcat(fname,"/");
3239 strcat(fname,name);
3240 strcat(fname,".LCK");
3242 f = fopen(fname,"r+");
3243 if (!f)
3245 DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
3246 return(False);
3249 fseek(f,0,SEEK_SET);
3251 /* find a free spot */
3252 for (i=0;i<max_connections;i++)
3254 if (fread(&crec,sizeof(crec),1,f) != 1)
3256 DEBUG(2,("Entry not found in lock file %s\n",fname));
3257 fclose(f);
3258 return(False);
3260 if (crec.pid == mypid && crec.cnum == cnum)
3261 break;
3264 if (crec.pid != mypid || crec.cnum != cnum)
3266 fclose(f);
3267 DEBUG(2,("Entry not found in lock file %s\n",fname));
3268 return(False);
3271 bzero((void *)&crec,sizeof(crec));
3273 /* remove our mark */
3274 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3275 fwrite(&crec,sizeof(crec),1,f) != 1)
3277 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3278 fclose(f);
3279 return(False);
3282 DEBUG(3,("Yield successful\n"));
3284 fclose(f);
3285 return(True);
3289 /****************************************************************************
3290 simple routines to do connection counting
3291 ****************************************************************************/
3292 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3294 struct connect_record crec;
3295 pstring fname;
3296 FILE *f;
3297 int snum = SNUM(cnum);
3298 int i,foundi= -1;
3299 int total_recs;
3301 if (max_connections <= 0)
3302 return(True);
3304 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3306 strcpy(fname,lp_lockdir());
3307 standard_sub(cnum,fname);
3308 trim_string(fname,"","/");
3310 if (!directory_exist(fname,NULL))
3311 mkdir(fname,0755);
3313 strcat(fname,"/");
3314 strcat(fname,name);
3315 strcat(fname,".LCK");
3317 if (!file_exist(fname,NULL))
3319 int oldmask = umask(022);
3320 f = fopen(fname,"w");
3321 if (f) fclose(f);
3322 umask(oldmask);
3325 total_recs = file_size(fname) / sizeof(crec);
3327 f = fopen(fname,"r+");
3329 if (!f)
3331 DEBUG(1,("couldn't open lock file %s\n",fname));
3332 return(False);
3335 /* find a free spot */
3336 for (i=0;i<max_connections;i++)
3339 if (i>=total_recs ||
3340 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3341 fread(&crec,sizeof(crec),1,f) != 1)
3343 if (foundi < 0) foundi = i;
3344 break;
3347 if (Clear && crec.pid && !process_exists(crec.pid))
3349 fseek(f,i*sizeof(crec),SEEK_SET);
3350 bzero((void *)&crec,sizeof(crec));
3351 fwrite(&crec,sizeof(crec),1,f);
3352 if (foundi < 0) foundi = i;
3353 continue;
3355 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3357 foundi=i;
3358 if (!Clear) break;
3362 if (foundi < 0)
3364 DEBUG(3,("no free locks in %s\n",fname));
3365 fclose(f);
3366 return(False);
3369 /* fill in the crec */
3370 bzero((void *)&crec,sizeof(crec));
3371 crec.magic = 0x280267;
3372 crec.pid = getpid();
3373 crec.cnum = cnum;
3374 crec.uid = Connections[cnum].uid;
3375 crec.gid = Connections[cnum].gid;
3376 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3377 crec.start = time(NULL);
3379 StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3380 StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3382 /* make our mark */
3383 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3384 fwrite(&crec,sizeof(crec),1,f) != 1)
3386 fclose(f);
3387 return(False);
3390 fclose(f);
3391 return(True);
3394 #if DUMP_CORE
3395 /*******************************************************************
3396 prepare to dump a core file - carefully!
3397 ********************************************************************/
3398 static BOOL dump_core(void)
3400 char *p;
3401 pstring dname;
3402 strcpy(dname,debugf);
3403 if ((p=strrchr(dname,'/'))) *p=0;
3404 strcat(dname,"/corefiles");
3405 mkdir(dname,0700);
3406 sys_chown(dname,getuid(),getgid());
3407 chmod(dname,0700);
3408 if (chdir(dname)) return(False);
3409 umask(~(0700));
3411 #ifndef NO_GETRLIMIT
3412 #ifdef RLIMIT_CORE
3414 struct rlimit rlp;
3415 getrlimit(RLIMIT_CORE, &rlp);
3416 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3417 setrlimit(RLIMIT_CORE, &rlp);
3418 getrlimit(RLIMIT_CORE, &rlp);
3419 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3421 #endif
3422 #endif
3425 DEBUG(0,("Dumping core in %s\n",dname));
3426 return(True);
3428 #endif
3430 /****************************************************************************
3431 exit the server
3432 ****************************************************************************/
3433 void exit_server(char *reason)
3435 static int firsttime=1;
3436 int i;
3438 if (!firsttime) exit(0);
3439 firsttime = 0;
3441 unbecome_user();
3442 DEBUG(2,("Closing connections\n"));
3443 for (i=0;i<MAX_CONNECTIONS;i++)
3444 if (Connections[i].open)
3445 close_cnum(i,(uint16)-1);
3446 #ifdef DFS_AUTH
3447 if (dcelogin_atmost_once)
3448 dfs_unlogin();
3449 #endif
3450 if (!reason) {
3451 int oldlevel = DEBUGLEVEL;
3452 DEBUGLEVEL = 10;
3453 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3454 if (last_inbuf)
3455 show_msg(last_inbuf);
3456 DEBUGLEVEL = oldlevel;
3457 DEBUG(0,("===============================================================\n"));
3458 #if DUMP_CORE
3459 if (dump_core()) return;
3460 #endif
3463 #ifdef FAST_SHARE_MODES
3464 stop_share_mode_mgmt();
3465 #endif /* FAST_SHARE_MODES */
3467 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3468 exit(0);
3471 /****************************************************************************
3472 do some standard substitutions in a string
3473 ****************************************************************************/
3474 void standard_sub(int cnum,char *string)
3476 if (VALID_CNUM(cnum)) {
3477 char *p, *s, *home;
3479 for ( s=string ; (p=strchr(s, '%')) != NULL ; s=p ) {
3480 switch (*(p+1)) {
3481 case 'H' : if ((home = get_home_dir(Connections[cnum].user))!=NULL)
3482 string_sub(p,"%H",home);
3483 else
3484 p += 2;
3485 break;
3486 case 'P' : string_sub(p,"%P",Connections[cnum].connectpath); break;
3487 case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break;
3488 case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break;
3489 case 'u' : string_sub(p,"%u",Connections[cnum].user); break;
3490 case '\0' : p++; break; /* don't run off the end of the string */
3491 default : p+=2; break;
3495 standard_sub_basic(string);
3499 These flags determine some of the permissions required to do an operation
3501 Note that I don't set NEED_WRITE on some write operations because they
3502 are used by some brain-dead clients when printing, and I don't want to
3503 force write permissions on print services.
3505 #define AS_USER (1<<0)
3506 #define NEED_WRITE (1<<1)
3507 #define TIME_INIT (1<<2)
3508 #define CAN_IPC (1<<3)
3509 #define AS_GUEST (1<<5)
3513 define a list of possible SMB messages and their corresponding
3514 functions. Any message that has a NULL function is unimplemented -
3515 please feel free to contribute implementations!
3517 struct smb_message_struct
3519 int code;
3520 char *name;
3521 int (*fn)();
3522 int flags;
3523 #if PROFILING
3524 unsigned long time;
3525 #endif
3527 smb_messages[] = {
3529 /* CORE PROTOCOL */
3531 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3532 {SMBtcon,"SMBtcon",reply_tcon,0},
3533 {SMBtdis,"SMBtdis",reply_tdis,0},
3534 {SMBexit,"SMBexit",reply_exit,0},
3535 {SMBioctl,"SMBioctl",reply_ioctl,0},
3536 {SMBecho,"SMBecho",reply_echo,0},
3537 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3538 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3539 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3540 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3541 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3542 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3543 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3544 {SMBopen,"SMBopen",reply_open,AS_USER},
3546 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3547 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3548 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3550 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3551 {SMBread,"SMBread",reply_read,AS_USER},
3552 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3553 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3554 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3555 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3556 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3557 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3559 /* this is a Pathworks specific call, allowing the
3560 changing of the root path */
3561 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3563 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3564 {SMBflush,"SMBflush",reply_flush,AS_USER},
3565 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3566 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3567 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3568 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3569 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3570 {SMBlock,"SMBlock",reply_lock,AS_USER},
3571 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3573 /* CORE+ PROTOCOL FOLLOWS */
3575 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3576 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3577 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3578 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3579 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3581 /* LANMAN1.0 PROTOCOL FOLLOWS */
3583 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3584 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3585 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3586 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3587 {SMBwritec,"SMBwritec",NULL,AS_USER},
3588 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3589 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3590 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3591 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3592 {SMBioctls,"SMBioctls",NULL,AS_USER},
3593 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3594 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3596 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3597 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3598 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3599 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3601 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3602 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3603 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3605 /* LANMAN2.0 PROTOCOL FOLLOWS */
3606 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3607 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3608 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3609 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3611 /* messaging routines */
3612 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3613 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3614 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3615 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3617 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3619 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3620 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3621 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3622 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3625 /****************************************************************************
3626 return a string containing the function name of a SMB command
3627 ****************************************************************************/
3628 char *smb_fn_name(int type)
3630 static char *unknown_name = "SMBunknown";
3631 static int num_smb_messages =
3632 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3633 int match;
3635 for (match=0;match<num_smb_messages;match++)
3636 if (smb_messages[match].code == type)
3637 break;
3639 if (match == num_smb_messages)
3640 return(unknown_name);
3642 return(smb_messages[match].name);
3646 /****************************************************************************
3647 do a switch on the message type, and return the response size
3648 ****************************************************************************/
3649 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3651 static int pid= -1;
3652 int outsize = 0;
3653 static int num_smb_messages =
3654 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3655 int match;
3657 #if PROFILING
3658 struct timeval msg_start_time;
3659 struct timeval msg_end_time;
3660 static unsigned long total_time = 0;
3662 GetTimeOfDay(&msg_start_time);
3663 #endif
3665 if (pid == -1)
3666 pid = getpid();
3668 errno = 0;
3669 last_message = type;
3671 /* make sure this is an SMB packet */
3672 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3674 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3675 return(-1);
3678 for (match=0;match<num_smb_messages;match++)
3679 if (smb_messages[match].code == type)
3680 break;
3682 if (match == num_smb_messages)
3684 DEBUG(0,("Unknown message type %d!\n",type));
3685 outsize = reply_unknown(inbuf,outbuf);
3687 else
3689 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3690 if (smb_messages[match].fn)
3692 int cnum = SVAL(inbuf,smb_tid);
3693 int flags = smb_messages[match].flags;
3694 uint16 session_tag = SVAL(inbuf,smb_uid);
3696 /* does this protocol need to be run as root? */
3697 if (!(flags & AS_USER))
3698 unbecome_user();
3700 /* does this protocol need to be run as the connected user? */
3701 if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3702 if (flags & AS_GUEST)
3703 flags &= ~AS_USER;
3704 else
3705 return(ERROR(ERRSRV,ERRinvnid));
3707 /* this code is to work around a bug is MS client 3 without
3708 introducing a security hole - it needs to be able to do
3709 print queue checks as guest if it isn't logged in properly */
3710 if (flags & AS_USER)
3711 flags &= ~AS_GUEST;
3713 /* does it need write permission? */
3714 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3715 return(ERROR(ERRSRV,ERRaccess));
3717 /* ipc services are limited */
3718 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3719 return(ERROR(ERRSRV,ERRaccess));
3721 /* load service specific parameters */
3722 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3723 return(ERROR(ERRSRV,ERRaccess));
3725 /* does this protocol need to be run as guest? */
3726 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3727 return(ERROR(ERRSRV,ERRaccess));
3729 last_inbuf = inbuf;
3731 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3733 else
3735 outsize = reply_unknown(inbuf,outbuf);
3739 #if PROFILING
3740 GetTimeOfDay(&msg_end_time);
3741 if (!(smb_messages[match].flags & TIME_INIT))
3743 smb_messages[match].time = 0;
3744 smb_messages[match].flags |= TIME_INIT;
3747 unsigned long this_time =
3748 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3749 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3750 smb_messages[match].time += this_time;
3751 total_time += this_time;
3753 DEBUG(2,("TIME %s %d usecs %g pct\n",
3754 smb_fn_name(type),smb_messages[match].time,
3755 (100.0*smb_messages[match].time) / total_time));
3756 #endif
3758 return(outsize);
3762 /****************************************************************************
3763 construct a chained reply and add it to the already made reply
3764 **************************************************************************/
3765 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3767 static char *orig_inbuf;
3768 static char *orig_outbuf;
3769 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3770 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3771 char *inbuf2, *outbuf2;
3772 int outsize2;
3773 char inbuf_saved[smb_wct];
3774 char outbuf_saved[smb_wct];
3775 extern int chain_size;
3776 int wct = CVAL(outbuf,smb_wct);
3777 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3779 /* maybe its not chained */
3780 if (smb_com2 == 0xFF) {
3781 CVAL(outbuf,smb_vwv0) = 0xFF;
3782 return outsize;
3785 if (chain_size == 0) {
3786 /* this is the first part of the chain */
3787 orig_inbuf = inbuf;
3788 orig_outbuf = outbuf;
3791 /* we need to tell the client where the next part of the reply will be */
3792 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3793 CVAL(outbuf,smb_vwv0) = smb_com2;
3795 /* remember how much the caller added to the chain, only counting stuff
3796 after the parameter words */
3797 chain_size += outsize - smb_wct;
3799 /* work out pointers into the original packets. The
3800 headers on these need to be filled in */
3801 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3802 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3804 /* remember the original command type */
3805 smb_com1 = CVAL(orig_inbuf,smb_com);
3807 /* save the data which will be overwritten by the new headers */
3808 memcpy(inbuf_saved,inbuf2,smb_wct);
3809 memcpy(outbuf_saved,outbuf2,smb_wct);
3811 /* give the new packet the same header as the last part of the SMB */
3812 memmove(inbuf2,inbuf,smb_wct);
3814 /* create the in buffer */
3815 CVAL(inbuf2,smb_com) = smb_com2;
3817 /* create the out buffer */
3818 bzero(outbuf2,smb_size);
3819 set_message(outbuf2,0,0,True);
3820 CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3822 memcpy(outbuf2+4,inbuf2+4,4);
3823 CVAL(outbuf2,smb_rcls) = SUCCESS;
3824 CVAL(outbuf2,smb_reh) = 0;
3825 CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
3826 means a reply */
3827 SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3828 SSVAL(outbuf2,smb_err,SUCCESS);
3829 SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3830 SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3831 SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3832 SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3834 DEBUG(3,("Chained message\n"));
3835 show_msg(inbuf2);
3837 /* process the request */
3838 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3839 bufsize-chain_size);
3841 /* copy the new reply and request headers over the old ones, but
3842 preserve the smb_com field */
3843 memmove(orig_outbuf,outbuf2,smb_wct);
3844 CVAL(orig_outbuf,smb_com) = smb_com1;
3846 /* restore the saved data, being careful not to overwrite any
3847 data from the reply header */
3848 memcpy(inbuf2,inbuf_saved,smb_wct);
3850 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3851 if (ofs < 0) ofs = 0;
3852 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3855 return outsize2;
3860 /****************************************************************************
3861 construct a reply to the incoming packet
3862 ****************************************************************************/
3863 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3865 int type = CVAL(inbuf,smb_com);
3866 int outsize = 0;
3867 int msg_type = CVAL(inbuf,0);
3868 extern int chain_size;
3870 smb_last_time = time(NULL);
3872 chain_size = 0;
3873 chain_fnum = -1;
3875 bzero(outbuf,smb_size);
3877 if (msg_type != 0)
3878 return(reply_special(inbuf,outbuf));
3880 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3881 set_message(outbuf,0,0,True);
3883 memcpy(outbuf+4,inbuf+4,4);
3884 CVAL(outbuf,smb_rcls) = SUCCESS;
3885 CVAL(outbuf,smb_reh) = 0;
3886 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3887 means a reply */
3888 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3889 SSVAL(outbuf,smb_err,SUCCESS);
3890 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3891 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3892 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3893 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3895 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3897 outsize += chain_size;
3899 if(outsize > 4)
3900 smb_setlen(outbuf,outsize - 4);
3901 return(outsize);
3905 /****************************************************************************
3906 process commands from the client
3907 ****************************************************************************/
3908 static void process(void)
3910 static int trans_num = 0;
3911 int nread;
3912 extern int Client;
3914 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3915 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3916 if ((InBuffer == NULL) || (OutBuffer == NULL))
3917 return;
3919 InBuffer += SMB_ALIGNMENT;
3920 OutBuffer += SMB_ALIGNMENT;
3922 #if PRIME_NMBD
3923 DEBUG(3,("priming nmbd\n"));
3925 struct in_addr ip;
3926 ip = *interpret_addr2("localhost");
3927 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3928 *OutBuffer = 0;
3929 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3931 #endif
3933 while (True)
3935 int32 len;
3936 int msg_type;
3937 int msg_flags;
3938 int type;
3939 int deadtime = lp_deadtime()*60;
3940 int counter;
3941 int last_keepalive=0;
3942 int service_load_counter = 0;
3944 if (deadtime <= 0)
3945 deadtime = DEFAULT_SMBD_TIMEOUT;
3947 if (lp_readprediction())
3948 do_read_prediction();
3950 errno = 0;
3952 for (counter=SMBD_SELECT_LOOP;
3953 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3954 counter += SMBD_SELECT_LOOP)
3956 int i;
3957 time_t t;
3958 BOOL allidle = True;
3959 extern int keepalive;
3961 if (counter > 365 * 3600) /* big number of seconds. */
3963 counter = 0;
3964 service_load_counter = 0;
3967 if (smb_read_error == READ_EOF) {
3968 DEBUG(3,("end of file from client\n"));
3969 return;
3972 if (smb_read_error == READ_ERROR) {
3973 DEBUG(3,("receive_smb error (%s) exiting\n",
3974 strerror(errno)));
3975 return;
3978 t = time(NULL);
3980 /* become root again if waiting */
3981 unbecome_user();
3983 /* check for smb.conf reload */
3984 if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
3986 service_load_counter = counter;
3988 /* reload services, if files have changed. */
3989 reload_services(True);
3992 /* automatic timeout if all connections are closed */
3993 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3994 DEBUG(2,("%s Closing idle connection\n",timestring()));
3995 return;
3998 if (keepalive && (counter-last_keepalive)>keepalive) {
3999 extern int password_client;
4000 if (!send_keepalive(Client)) {
4001 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
4002 return;
4004 /* also send a keepalive to the password server if its still
4005 connected */
4006 if (password_client != -1)
4007 send_keepalive(password_client);
4008 last_keepalive = counter;
4011 /* check for connection timeouts */
4012 for (i=0;i<MAX_CONNECTIONS;i++)
4013 if (Connections[i].open)
4015 /* close dirptrs on connections that are idle */
4016 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
4017 dptr_idlecnum(i);
4019 if (Connections[i].num_files_open > 0 ||
4020 (t-Connections[i].lastused)<deadtime)
4021 allidle = False;
4024 if (allidle && num_connections_open>0) {
4025 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
4026 return;
4030 msg_type = CVAL(InBuffer,0);
4031 msg_flags = CVAL(InBuffer,1);
4032 type = CVAL(InBuffer,smb_com);
4034 len = smb_len(InBuffer);
4036 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
4038 nread = len + 4;
4040 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
4042 #ifdef WITH_VTP
4043 if(trans_num == 1 && VT_Check(InBuffer)) {
4044 VT_Process();
4045 return;
4047 #endif
4050 if (msg_type == 0)
4051 show_msg(InBuffer);
4053 nread = construct_reply(InBuffer,OutBuffer,nread,max_send);
4055 if(nread > 0) {
4056 if (CVAL(OutBuffer,0) == 0)
4057 show_msg(OutBuffer);
4059 if (nread != smb_len(OutBuffer) + 4)
4061 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
4062 nread,
4063 smb_len(OutBuffer)));
4065 else
4066 send_smb(Client,OutBuffer);
4068 trans_num++;
4073 /****************************************************************************
4074 initialise connect, service and file structs
4075 ****************************************************************************/
4076 static void init_structs(void )
4078 int i;
4079 get_myname(myhostname,NULL);
4081 for (i=0;i<MAX_CONNECTIONS;i++)
4083 Connections[i].open = False;
4084 Connections[i].num_files_open=0;
4085 Connections[i].lastused=0;
4086 Connections[i].used=False;
4087 string_init(&Connections[i].user,"");
4088 string_init(&Connections[i].dirpath,"");
4089 string_init(&Connections[i].connectpath,"");
4090 string_init(&Connections[i].origpath,"");
4093 for (i=0;i<MAX_OPEN_FILES;i++)
4095 Files[i].open = False;
4096 string_init(&Files[i].name,"");
4100 for (i=0;i<MAX_OPEN_FILES;i++)
4102 file_fd_struct *fd_ptr = &FileFd[i];
4103 fd_ptr->ref_count = 0;
4104 fd_ptr->dev = (int32)-1;
4105 fd_ptr->inode = (int32)-1;
4106 fd_ptr->fd = -1;
4107 fd_ptr->fd_readonly = -1;
4108 fd_ptr->fd_writeonly = -1;
4109 fd_ptr->real_open_flags = -1;
4112 init_dptrs();
4115 /****************************************************************************
4116 usage on the program
4117 ****************************************************************************/
4118 static void usage(char *pname)
4120 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4122 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
4123 printf("Version %s\n",VERSION);
4124 printf("\t-D become a daemon\n");
4125 printf("\t-p port listen on the specified port\n");
4126 printf("\t-d debuglevel set the debuglevel\n");
4127 printf("\t-l log basename. Basename for log/debug files\n");
4128 printf("\t-s services file. Filename of services file\n");
4129 printf("\t-P passive only\n");
4130 printf("\t-a overwrite log file, don't append\n");
4131 printf("\n");
4135 /****************************************************************************
4136 main program
4137 ****************************************************************************/
4138 int main(int argc,char *argv[])
4140 extern BOOL append_log;
4141 /* shall I run as a daemon */
4142 BOOL is_daemon = False;
4143 int port = SMB_PORT;
4144 int opt;
4145 extern char *optarg;
4146 char pidFile[100] = { 0 };
4148 #ifdef NEED_AUTH_PARAMETERS
4149 set_auth_parameters(argc,argv);
4150 #endif
4152 #ifdef SecureWare
4153 setluid(0);
4154 #endif
4156 append_log = True;
4158 TimeInit();
4160 strcpy(debugf,SMBLOGFILE);
4162 setup_logging(argv[0],False);
4164 charset_initialise();
4166 /* make absolutely sure we run as root - to handle cases whre people
4167 are crazy enough to have it setuid */
4168 #ifdef USE_SETRES
4169 setresuid(0,0,0);
4170 #else
4171 setuid(0);
4172 seteuid(0);
4173 setuid(0);
4174 seteuid(0);
4175 #endif
4177 fault_setup(exit_server);
4178 signal(SIGTERM , SIGNAL_CAST dflt_sig);
4180 /* we want total control over the permissions on created files,
4181 so set our umask to 0 */
4182 umask(0);
4184 GetWd(OriginalDir);
4186 init_uid();
4188 /* this is for people who can't start the program correctly */
4189 while (argc > 1 && (*argv[1] != '-'))
4191 argv++;
4192 argc--;
4195 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
4196 switch (opt)
4198 case 'f':
4199 strncpy(pidFile, optarg, sizeof(pidFile));
4200 break;
4201 case 'O':
4202 strcpy(user_socket_options,optarg);
4203 break;
4204 case 'i':
4205 strcpy(scope,optarg);
4206 break;
4207 case 'P':
4209 extern BOOL passive;
4210 passive = True;
4212 break;
4213 case 's':
4214 strcpy(servicesf,optarg);
4215 break;
4216 case 'l':
4217 strcpy(debugf,optarg);
4218 break;
4219 case 'a':
4221 extern BOOL append_log;
4222 append_log = !append_log;
4224 break;
4225 case 'D':
4226 is_daemon = True;
4227 break;
4228 case 'd':
4229 if (*optarg == 'A')
4230 DEBUGLEVEL = 10000;
4231 else
4232 DEBUGLEVEL = atoi(optarg);
4233 break;
4234 case 'p':
4235 port = atoi(optarg);
4236 break;
4237 case 'h':
4238 usage(argv[0]);
4239 exit(0);
4240 break;
4241 default:
4242 usage(argv[0]);
4243 exit(1);
4246 reopen_logs();
4248 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4249 DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n"));
4251 #ifndef NO_GETRLIMIT
4252 #ifdef RLIMIT_NOFILE
4254 struct rlimit rlp;
4255 getrlimit(RLIMIT_NOFILE, &rlp);
4256 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4257 setrlimit(RLIMIT_NOFILE, &rlp);
4258 getrlimit(RLIMIT_NOFILE, &rlp);
4259 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4261 #endif
4262 #endif
4265 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4266 getuid(),getgid(),geteuid(),getegid()));
4268 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4270 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4271 exit(1);
4274 init_structs();
4276 if (!reload_services(False))
4277 return(-1);
4279 codepage_initialise(lp_client_code_page());
4281 strcpy(myworkgroup, lp_workgroup());
4283 #ifndef NO_SIGNAL_TEST
4284 signal(SIGHUP,SIGNAL_CAST sig_hup);
4285 #endif
4287 DEBUG(3,("%s loaded services\n",timestring()));
4289 if (!is_daemon && !is_a_socket(0))
4291 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4292 is_daemon = True;
4295 if (is_daemon)
4297 DEBUG(3,("%s becoming a daemon\n",timestring()));
4298 become_daemon();
4301 if (*pidFile)
4303 int fd;
4304 char buf[20];
4306 if ((fd = open(pidFile,
4307 #ifdef O_NONBLOCK
4308 O_NONBLOCK |
4309 #endif
4310 O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4312 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4313 exit(1);
4315 if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4317 DEBUG(0,("ERROR: smbd is already running\n"));
4318 exit(1);
4320 sprintf(buf, "%u\n", (unsigned int) getpid());
4321 if (write(fd, buf, strlen(buf)) < 0)
4323 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4324 exit(1);
4326 /* Leave pid file open & locked for the duration... */
4329 if (!open_sockets(is_daemon,port))
4330 exit(1);
4332 #ifdef FAST_SHARE_MODES
4333 if (!start_share_mode_mgmt())
4334 exit(1);
4335 #endif /* FAST_SHARE_MODES */
4337 /* possibly reload the services file. */
4338 reload_services(True);
4340 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
4342 if (*lp_rootdir())
4344 if (sys_chroot(lp_rootdir()) == 0)
4345 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4348 process();
4349 close_sockets();
4351 exit_server("normal exit");
4352 return(0);