Makefile: Added krb5 option from Nathan Neulinger <nneul@umr.edu>
[Samba.git] / source / smbd / server.c
blob296962421560b0bffbeffb6dc1962cd7bcf8b066
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 ((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(SNUM(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 snum,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))) {
375 strcpy(name, dname);
376 return(True);
379 if (mangled)
380 check_mangled_stack(name);
382 /* open the directory */
383 if (!(cur_dir = OpenDir(snum, 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)) 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);
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.
429 ****************************************************************************/
430 BOOL unix_convert(char *name,int cnum,pstring saved_last_component)
432 struct stat st;
433 char *start, *end;
434 pstring dirpath;
436 *dirpath = 0;
437 if(saved_last_component)
438 *saved_last_component = 0;
440 /* convert to basic unix format - removing \ chars and cleaning it up */
441 unix_format(name);
442 unix_clean_name(name);
444 /* names must be relative to the root of the service - trim any leading /.
445 also trim trailing /'s */
446 trim_string(name,"/","/");
449 * Ensure saved_last_component is valid even if file exists.
451 if(saved_last_component) {
452 end = strrchr(name, '/');
453 if(end)
454 strcpy(saved_last_component, end + 1);
455 else
456 strcpy(saved_last_component, name);
459 if (!case_sensitive &&
460 (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
461 strnorm(name);
463 /* check if it's a printer file */
464 if (Connections[cnum].printer)
466 if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
468 char *s;
469 fstring name2;
470 sprintf(name2,"%.6s.XXXXXX",remote_machine);
471 /* sanitise the name */
472 for (s=name2 ; *s ; s++)
473 if (!issafe(*s)) *s = '_';
474 strcpy(name,(char *)mktemp(name2));
476 return(True);
479 /* stat the name - if it exists then we are all done! */
480 if (sys_stat(name,&st) == 0)
481 return(True);
483 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
485 /* a special case - if we don't have any mangling chars and are case
486 sensitive then searching won't help */
487 if (case_sensitive && !is_mangled(name) &&
488 !lp_strip_dot() && !use_mangled_map)
489 return(False);
491 /* now we need to recursively match the name against the real
492 directory structure */
494 start = name;
495 while (strncmp(start,"./",2) == 0)
496 start += 2;
498 /* now match each part of the path name separately, trying the names
499 as is first, then trying to scan the directory for matching names */
500 for (;start;start = (end?end+1:(char *)NULL))
502 /* pinpoint the end of this section of the filename */
503 end = strchr(start, '/');
505 /* chop the name at this point */
506 if (end) *end = 0;
508 if(saved_last_component != 0)
509 strcpy(saved_last_component, end ? end + 1 : start);
511 /* check if the name exists up to this point */
512 if (sys_stat(name, &st) == 0)
514 /* it exists. it must either be a directory or this must be
515 the last part of the path for it to be OK */
516 if (end && !(st.st_mode & S_IFDIR))
518 /* an intermediate part of the name isn't a directory */
519 DEBUG(5,("Not a dir %s\n",start));
520 *end = '/';
521 return(False);
524 else
526 pstring rest;
528 *rest = 0;
530 /* remember the rest of the pathname so it can be restored
531 later */
532 if (end) strcpy(rest,end+1);
534 /* try to find this part of the path in the directory */
535 if (strchr(start,'?') || strchr(start,'*') ||
536 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
538 if (end)
540 /* an intermediate part of the name can't be found */
541 DEBUG(5,("Intermediate not found %s\n",start));
542 *end = '/';
543 return(False);
546 /* just the last part of the name doesn't exist */
547 /* we may need to strupper() or strlower() it in case
548 this conversion is being used for file creation
549 purposes */
550 /* if the filename is of mixed case then don't normalise it */
551 if (!case_preserve &&
552 (!strhasupper(start) || !strhaslower(start)))
553 strnorm(start);
555 /* check on the mangled stack to see if we can recover the
556 base of the filename */
557 if (is_mangled(start))
558 check_mangled_stack(start);
560 DEBUG(5,("New file %s\n",start));
561 return(True);
564 /* restore the rest of the string */
565 if (end)
567 strcpy(start+strlen(start)+1,rest);
568 end = start + strlen(start);
572 /* add to the dirpath that we have resolved so far */
573 if (*dirpath) strcat(dirpath,"/");
574 strcat(dirpath,start);
576 /* restore the / that we wiped out earlier */
577 if (end) *end = '/';
580 /* the name has been resolved */
581 DEBUG(5,("conversion finished %s\n",name));
582 return(True);
586 /****************************************************************************
587 normalise for DOS usage
588 ****************************************************************************/
589 static void disk_norm(int *bsize,int *dfree,int *dsize)
591 /* check if the disk is beyond the max disk size */
592 int maxdisksize = lp_maxdisksize();
593 if (maxdisksize) {
594 /* convert to blocks - and don't overflow */
595 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
596 if (*dsize > maxdisksize) *dsize = maxdisksize;
597 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
598 applications getting
599 div by 0 errors */
602 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
604 *dfree /= 2;
605 *dsize /= 2;
606 *bsize *= 2;
607 if (*bsize > WORDMAX )
609 *bsize = WORDMAX;
610 if (*dsize > WORDMAX)
611 *dsize = WORDMAX;
612 if (*dfree > WORDMAX)
613 *dfree = WORDMAX;
614 break;
619 /****************************************************************************
620 return number of 1K blocks available on a path and total number
621 ****************************************************************************/
622 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
624 char *df_command = lp_dfree_command();
625 int dfree_retval;
626 #ifdef QUOTAS
627 int dfreeq_retval;
628 int dfreeq = 0;
629 int bsizeq = *bsize;
630 int dsizeq = *dsize;
631 #endif
633 #ifndef NO_STATFS
634 #ifdef USE_STATVFS
635 struct statvfs fs;
636 #else
637 #ifdef ULTRIX
638 struct fs_data fs;
639 #else
640 struct statfs fs;
641 #endif
642 #endif
643 #endif
645 /* possibly use system() to get the result */
646 if (df_command && *df_command)
648 int ret;
649 pstring syscmd;
650 pstring outfile;
652 sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
653 sprintf(syscmd,"%s %s",df_command,path);
654 standard_sub_basic(syscmd);
656 ret = smbrun(syscmd,outfile,False);
657 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
660 FILE *f = fopen(outfile,"r");
661 *dsize = 0;
662 *dfree = 0;
663 *bsize = 1024;
664 if (f)
666 fscanf(f,"%d %d %d",dsize,dfree,bsize);
667 fclose(f);
669 else
670 DEBUG(0,("Can't open %s\n",outfile));
673 unlink(outfile);
674 disk_norm(bsize,dfree,dsize);
675 dfree_retval = ((*bsize)/1024)*(*dfree);
676 #ifdef QUOTAS
677 /* Ensure we return the min value between the users quota and
678 what's free on the disk. Thanks to Albrecht Gebhardt
679 <albrecht.gebhardt@uni-klu.ac.at> for this fix.
681 if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
683 disk_norm(&bsizeq, &dfreeq, &dsizeq);
684 dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
685 dfree_retval = ( dfree_retval < dfreeq_retval ) ?
686 dfree_retval : dfreeq_retval ;
687 /* maybe dfree and dfreeq are calculated using different bsizes
688 so convert dfree from bsize into bsizeq */
689 *dfree = ((*dfree) * (*bsize)) / (bsizeq);
690 *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
691 *bsize = bsizeq;
692 *dsize = dsizeq;
694 #endif
695 return(dfree_retval);
698 #ifdef NO_STATFS
699 DEBUG(1,("Warning - no statfs function\n"));
700 return(1);
701 #else
702 #ifdef STATFS4
703 if (statfs(path,&fs,sizeof(fs),0) != 0)
704 #else
705 #ifdef USE_STATVFS
706 if (statvfs(path, &fs))
707 #else
708 #ifdef STATFS3
709 if (statfs(path,&fs,sizeof(fs)) == -1)
710 #else
711 if (statfs(path,&fs) == -1)
712 #endif /* STATFS3 */
713 #endif /* USE_STATVFS */
714 #endif /* STATFS4 */
716 DEBUG(3,("dfree call failed code errno=%d\n",errno));
717 *bsize = 1024;
718 *dfree = 1;
719 *dsize = 1;
720 return(((*bsize)/1024)*(*dfree));
723 #ifdef ULTRIX
724 *bsize = 1024;
725 *dfree = fs.fd_req.bfree;
726 *dsize = fs.fd_req.btot;
727 #else
728 #ifdef USE_STATVFS
729 *bsize = fs.f_frsize;
730 #else
731 #ifdef USE_F_FSIZE
732 /* eg: osf1 has f_fsize = fundamental filesystem block size,
733 f_bsize = optimal transfer block size (MX: 94-04-19) */
734 *bsize = fs.f_fsize;
735 #else
736 *bsize = fs.f_bsize;
737 #endif /* STATFS3 */
738 #endif /* USE_STATVFS */
740 #ifdef STATFS4
741 *dfree = fs.f_bfree;
742 #else
743 *dfree = fs.f_bavail;
744 #endif /* STATFS4 */
745 *dsize = fs.f_blocks;
746 #endif /* ULTRIX */
748 #if defined(SCO) || defined(ISC) || defined(MIPS)
749 *bsize = 512;
750 #endif
752 /* handle rediculous bsize values - some OSes are broken */
753 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
755 disk_norm(bsize,dfree,dsize);
757 if (*bsize < 256)
758 *bsize = 512;
759 if ((*dsize)<1)
761 DEBUG(0,("dfree seems to be broken on your system\n"));
762 *dsize = 20*1024*1024/(*bsize);
763 *dfree = MAX(1,*dfree);
765 dfree_retval = ((*bsize)/1024)*(*dfree);
766 #ifdef QUOTAS
767 /* Ensure we return the min value between the users quota and
768 what's free on the disk. Thanks to Albrecht Gebhardt
769 <albrecht.gebhardt@uni-klu.ac.at> for this fix.
771 if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
773 disk_norm(&bsizeq, &dfreeq, &dsizeq);
774 dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
775 dfree_retval = ( dfree_retval < dfreeq_retval ) ?
776 dfree_retval : dfreeq_retval ;
777 /* maybe dfree and dfreeq are calculated using different bsizes
778 so convert dfree from bsize into bsizeq */
779 *dfree = ((*dfree) * (*bsize)) / (bsizeq);
780 *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
781 *bsize = bsizeq;
782 *dsize = dsizeq;
784 #endif
785 return(dfree_retval);
786 #endif
790 /****************************************************************************
791 wrap it to get filenames right
792 ****************************************************************************/
793 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
795 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
800 /****************************************************************************
801 check a filename - possibly caling reducename
803 This is called by every routine before it allows an operation on a filename.
804 It does any final confirmation necessary to ensure that the filename is
805 a valid one for the user to access.
806 ****************************************************************************/
807 BOOL check_name(char *name,int cnum)
809 BOOL ret;
811 errno = 0;
813 if( is_vetoed_name(SNUM(cnum), name))
815 DEBUG(5,("file path name %s vetoed\n",name));
816 return(0);
819 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
820 if (!ret)
821 DEBUG(5,("check_name on %s failed\n",name));
823 return(ret);
826 /****************************************************************************
827 check a filename - possibly caling reducename
828 ****************************************************************************/
829 static void check_for_pipe(char *fname)
831 /* special case of pipe opens */
832 char s[10];
833 StrnCpy(s,fname,9);
834 strlower(s);
835 if (strstr(s,"pipe/"))
837 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
838 unix_ERR_class = ERRSRV;
839 unix_ERR_code = ERRaccess;
843 /****************************************************************************
844 fd support routines - attempt to do a sys_open
845 ****************************************************************************/
847 int fd_attempt_open(char *fname, int flags, int mode)
849 int fd = sys_open(fname,flags,mode);
851 /* Fix for files ending in '.' */
852 if((fd == -1) && (errno == ENOENT) &&
853 (strchr(fname,'.')==NULL))
855 strcat(fname,".");
856 fd = sys_open(fname,flags,mode);
859 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
860 if ((fd == -1) && (errno == ENAMETOOLONG))
862 int max_len;
863 char *p = strrchr(fname, '/');
865 if (p == fname) /* name is "/xxx" */
867 max_len = pathconf("/", _PC_NAME_MAX);
868 p++;
870 else if ((p == NULL) || (p == fname))
872 p = fname;
873 max_len = pathconf(".", _PC_NAME_MAX);
875 else
877 *p = '\0';
878 max_len = pathconf(fname, _PC_NAME_MAX);
879 *p = '/';
880 p++;
882 if (strlen(p) > max_len)
884 char tmp = p[max_len];
886 p[max_len] = '\0';
887 if ((fd = sys_open(fname,flags,mode)) == -1)
888 p[max_len] = tmp;
891 #endif
892 return fd;
895 /****************************************************************************
896 fd support routines - attempt to find an already open file by dev
897 and inode - increments the ref_count of the returned file_fd_struct *.
898 ****************************************************************************/
899 file_fd_struct *fd_get_already_open(struct stat *sbuf)
901 int i;
902 file_fd_struct *fd_ptr;
904 if(sbuf == 0)
905 return 0;
907 for(i = 0; i <= max_file_fd_used; i++) {
908 fd_ptr = &FileFd[i];
909 if((fd_ptr->ref_count > 0) &&
910 (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
911 (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
912 fd_ptr->ref_count++;
913 DEBUG(3,
914 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
915 i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
916 return fd_ptr;
919 return 0;
922 /****************************************************************************
923 fd support routines - attempt to find a empty slot in the FileFd array.
924 Increments the ref_count of the returned entry.
925 ****************************************************************************/
926 file_fd_struct *fd_get_new()
928 int i;
929 file_fd_struct *fd_ptr;
931 for(i = 0; i < MAX_OPEN_FILES; i++) {
932 fd_ptr = &FileFd[i];
933 if(fd_ptr->ref_count == 0) {
934 fd_ptr->dev = (uint32)-1;
935 fd_ptr->inode = (uint32)-1;
936 fd_ptr->fd = -1;
937 fd_ptr->fd_readonly = -1;
938 fd_ptr->fd_writeonly = -1;
939 fd_ptr->real_open_flags = -1;
940 fd_ptr->ref_count++;
941 /* Increment max used counter if neccessary, cuts down
942 on search time when re-using */
943 if(i > max_file_fd_used)
944 max_file_fd_used = i;
945 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
946 i, fd_ptr->dev, fd_ptr->inode));
947 return fd_ptr;
950 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
951 n"));
952 return 0;
955 /****************************************************************************
956 fd support routines - attempt to re-open an already open fd as O_RDWR.
957 Save the already open fd (we cannot close due to POSIX file locking braindamage.
958 ****************************************************************************/
960 void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
962 int fd = sys_open( fname, O_RDWR, mode);
964 if(fd == -1)
965 return;
967 if(fd_ptr->real_open_flags == O_RDONLY)
968 fd_ptr->fd_readonly = fd_ptr->fd;
969 if(fd_ptr->real_open_flags == O_WRONLY)
970 fd_ptr->fd_writeonly = fd_ptr->fd;
972 fd_ptr->fd = fd;
973 fd_ptr->real_open_flags = O_RDWR;
976 /****************************************************************************
977 fd support routines - attempt to close the file referenced by this fd.
978 Decrements the ref_count and returns it.
979 ****************************************************************************/
980 int fd_attempt_close(file_fd_struct *fd_ptr)
982 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
983 fd_ptr - &FileFd[0],
984 fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
985 fd_ptr->real_open_flags,
986 fd_ptr->ref_count));
987 if(fd_ptr->ref_count > 0) {
988 fd_ptr->ref_count--;
989 if(fd_ptr->ref_count == 0) {
990 if(fd_ptr->fd != -1)
991 close(fd_ptr->fd);
992 if(fd_ptr->fd_readonly != -1)
993 close(fd_ptr->fd_readonly);
994 if(fd_ptr->fd_writeonly != -1)
995 close(fd_ptr->fd_writeonly);
996 fd_ptr->fd = -1;
997 fd_ptr->fd_readonly = -1;
998 fd_ptr->fd_writeonly = -1;
999 fd_ptr->real_open_flags = -1;
1000 fd_ptr->dev = (uint32)-1;
1001 fd_ptr->inode = (uint32)-1;
1004 return fd_ptr->ref_count;
1007 /****************************************************************************
1008 open a file
1009 ****************************************************************************/
1010 static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
1012 extern struct current_user current_user;
1013 pstring fname;
1014 struct stat statbuf;
1015 file_fd_struct *fd_ptr;
1017 Files[fnum].open = False;
1018 Files[fnum].fd_ptr = 0;
1019 errno = EPERM;
1021 strcpy(fname,fname1);
1023 /* check permissions */
1024 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
1026 DEBUG(3,("Permission denied opening %s\n",fname));
1027 check_for_pipe(fname);
1028 return;
1031 /* this handles a bug in Win95 - it doesn't say to create the file when it
1032 should */
1033 if (Connections[cnum].printer)
1034 flags |= O_CREAT;
1037 if (flags == O_WRONLY)
1038 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
1041 #if UTIME_WORKAROUND
1042 /* XXXX - is this OK?? */
1043 /* this works around a utime bug but can cause other problems */
1044 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
1045 sys_unlink(fname);
1046 #endif
1049 * Ensure we have a valid struct stat so we can search the
1050 * open fd table.
1052 if(sbuf == 0) {
1053 if(stat(fname, &statbuf) < 0) {
1054 if(errno != ENOENT) {
1055 DEBUG(3,("Error doing stat on file %s (%s)\n",
1056 fname,strerror(errno)));
1058 check_for_pipe(fname);
1059 return;
1061 sbuf = 0;
1062 } else {
1063 sbuf = &statbuf;
1068 * Check to see if we have this file already
1069 * open. If we do, just use the already open fd and increment the
1070 * reference count (fd_get_already_open increments the ref_count).
1072 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
1074 int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
1076 /* File was already open. */
1077 if((flags & O_CREAT) && (flags & O_EXCL)) {
1078 fd_ptr->ref_count--;
1079 errno = EEXIST;
1080 return;
1084 * If not opened O_RDWR try
1085 * and do that here - a chmod may have been done
1086 * between the last open and now.
1088 if(fd_ptr->real_open_flags != O_RDWR)
1089 fd_attempt_reopen(fname, mode, fd_ptr);
1092 * Ensure that if we wanted write access
1093 * it has been opened for write, and if we wanted read it
1094 * was open for read.
1096 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1097 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1098 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1099 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1100 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1101 check_for_pipe(fname);
1102 fd_ptr->ref_count--;
1103 return;
1106 } else {
1107 int open_flags;
1108 /* We need to allocate a new file_fd_struct (this increments the
1109 ref_count). */
1110 if((fd_ptr = fd_get_new()) == 0)
1111 return;
1113 * Whatever the requested flags, attempt read/write access,
1114 * as we don't know what flags future file opens may require.
1115 * If this fails, try again with the required flags.
1116 * Even if we open read/write when only read access was
1117 * requested the setting of the can_write flag in
1118 * the file_struct will protect us from errant
1119 * write requests. We never need to worry about O_APPEND
1120 * as this is not set anywhere in Samba.
1122 fd_ptr->real_open_flags = O_RDWR;
1123 /* Set the flags as needed without the read/write modes. */
1124 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1125 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1127 * On some systems opening a file for R/W access on a read only
1128 * filesystems sets errno to EROFS.
1130 #ifdef EROFS
1131 if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1132 #else /* No EROFS */
1133 if((fd_ptr->fd == -1) && (errno == EACCES)) {
1134 #endif /* EROFS */
1135 if(flags & O_WRONLY) {
1136 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1137 fd_ptr->real_open_flags = O_WRONLY;
1138 } else {
1139 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1140 fd_ptr->real_open_flags = O_RDONLY;
1145 if ((fd_ptr->fd >=0) &&
1146 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1147 pstring dname;
1148 int dum1,dum2,dum3;
1149 char *p;
1150 strcpy(dname,fname);
1151 p = strrchr(dname,'/');
1152 if (p) *p = 0;
1153 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1154 lp_minprintspace(SNUM(cnum))) {
1155 fd_attempt_close(fd_ptr);
1156 Files[fnum].fd_ptr = 0;
1157 if(fd_ptr->ref_count == 0)
1158 sys_unlink(fname);
1159 errno = ENOSPC;
1160 return;
1164 if (fd_ptr->fd < 0)
1166 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1167 fname,strerror(errno),flags));
1168 /* Ensure the ref_count is decremented. */
1169 fd_attempt_close(fd_ptr);
1170 check_for_pipe(fname);
1171 return;
1174 if (fd_ptr->fd >= 0)
1176 if(sbuf == 0) {
1177 /* Do the fstat */
1178 if(fstat(fd_ptr->fd, &statbuf) == -1) {
1179 /* Error - backout !! */
1180 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1181 fd_ptr->fd, fname,strerror(errno)));
1182 /* Ensure the ref_count is decremented. */
1183 fd_attempt_close(fd_ptr);
1184 return;
1186 sbuf = &statbuf;
1188 /* Set the correct entries in fd_ptr. */
1189 fd_ptr->dev = (uint32)sbuf->st_dev;
1190 fd_ptr->inode = (uint32)sbuf->st_ino;
1192 Files[fnum].fd_ptr = fd_ptr;
1193 Connections[cnum].num_files_open++;
1194 Files[fnum].mode = sbuf->st_mode;
1195 GetTimeOfDay(&Files[fnum].open_time);
1196 Files[fnum].uid = current_user.id;
1197 Files[fnum].size = 0;
1198 Files[fnum].pos = -1;
1199 Files[fnum].open = True;
1200 Files[fnum].mmap_ptr = NULL;
1201 Files[fnum].mmap_size = 0;
1202 Files[fnum].can_lock = True;
1203 Files[fnum].can_read = ((flags & O_WRONLY)==0);
1204 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1205 Files[fnum].share_mode = 0;
1206 Files[fnum].print_file = Connections[cnum].printer;
1207 Files[fnum].modified = False;
1208 Files[fnum].cnum = cnum;
1209 string_set(&Files[fnum].name,dos_to_unix(fname,False));
1210 Files[fnum].wbmpx_ptr = NULL;
1213 * If the printer is marked as postscript output a leading
1214 * file identifier to ensure the file is treated as a raw
1215 * postscript file.
1216 * This has a similar effect as CtrlD=0 in WIN.INI file.
1217 * tim@fsg.com 09/06/94
1219 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
1220 Files[fnum].can_write)
1222 DEBUG(3,("Writing postscript line\n"));
1223 write_file(fnum,"%!\n",3);
1226 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1227 timestring(),Connections[cnum].user,fname,
1228 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1229 Connections[cnum].num_files_open,fnum));
1233 #if USE_MMAP
1234 /* mmap it if read-only */
1235 if (!Files[fnum].can_write)
1237 Files[fnum].mmap_size = file_size(fname);
1238 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1239 PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
1241 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1243 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1244 Files[fnum].mmap_ptr = NULL;
1247 #endif
1250 /*******************************************************************
1251 sync a file
1252 ********************************************************************/
1253 void sync_file(int fnum)
1255 #ifndef NO_FSYNC
1256 fsync(Files[fnum].fd_ptr->fd);
1257 #endif
1260 /****************************************************************************
1261 run a file if it is a magic script
1262 ****************************************************************************/
1263 static void check_magic(int fnum,int cnum)
1265 if (!*lp_magicscript(SNUM(cnum)))
1266 return;
1268 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1271 char *p;
1272 if (!(p = strrchr(Files[fnum].name,'/')))
1273 p = Files[fnum].name;
1274 else
1275 p++;
1277 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1278 return;
1282 int ret;
1283 pstring magic_output;
1284 pstring fname;
1285 strcpy(fname,Files[fnum].name);
1287 if (*lp_magicoutput(SNUM(cnum)))
1288 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1289 else
1290 sprintf(magic_output,"%s.out",fname);
1292 chmod(fname,0755);
1293 ret = smbrun(fname,magic_output,False);
1294 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1295 unlink(fname);
1300 /****************************************************************************
1301 close a file - possibly invalidating the read prediction
1302 ****************************************************************************/
1303 void close_file(int fnum)
1305 files_struct *fs_p = &Files[fnum];
1306 int cnum = fs_p->cnum;
1307 uint32 dev = fs_p->fd_ptr->dev;
1308 uint32 inode = fs_p->fd_ptr->inode;
1309 share_lock_token token;
1311 invalidate_read_prediction(fs_p->fd_ptr->fd);
1312 fs_p->open = False;
1313 Connections[cnum].num_files_open--;
1314 if(fs_p->wbmpx_ptr)
1316 free((char *)fs_p->wbmpx_ptr);
1317 fs_p->wbmpx_ptr = NULL;
1320 #if USE_MMAP
1321 if(fs_p->mmap_ptr)
1323 munmap(fs_p->mmap_ptr,fs_p->mmap_size);
1324 fs_p->mmap_ptr = NULL;
1326 #endif
1328 if (lp_share_modes(SNUM(cnum)))
1330 lock_share_entry( cnum, dev, inode, &token);
1331 del_share_mode(token, fnum);
1334 fd_attempt_close(fs_p->fd_ptr);
1336 if (lp_share_modes(SNUM(cnum)))
1337 unlock_share_entry( cnum, dev, inode, token);
1339 /* NT uses smbclose to start a print - weird */
1340 if (fs_p->print_file)
1341 print_file(fnum);
1343 /* check for magic scripts */
1344 check_magic(fnum,cnum);
1346 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1347 timestring(),Connections[cnum].user,fs_p->name,
1348 Connections[cnum].num_files_open));
1351 enum {AFAIL,AREAD,AWRITE,AALL};
1353 /*******************************************************************
1354 reproduce the share mode access table
1355 ********************************************************************/
1356 static int access_table(int new_deny,int old_deny,int old_mode,
1357 int share_pid,char *fname)
1359 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1361 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1362 if (old_deny == new_deny && share_pid == getpid())
1363 return(AALL);
1365 if (old_mode == 0) return(AREAD);
1367 /* the new smbpub.zip spec says that if the file extension is
1368 .com, .dll, .exe or .sym then allow the open. I will force
1369 it to read-only as this seems sensible although the spec is
1370 a little unclear on this. */
1371 if ((fname = strrchr(fname,'.'))) {
1372 if (strequal(fname,".com") ||
1373 strequal(fname,".dll") ||
1374 strequal(fname,".exe") ||
1375 strequal(fname,".sym"))
1376 return(AREAD);
1379 return(AFAIL);
1382 switch (new_deny)
1384 case DENY_WRITE:
1385 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1386 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1387 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1388 return(AFAIL);
1389 case DENY_READ:
1390 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1391 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1392 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1393 return(AFAIL);
1394 case DENY_NONE:
1395 if (old_deny==DENY_WRITE) return(AREAD);
1396 if (old_deny==DENY_READ) return(AWRITE);
1397 if (old_deny==DENY_NONE) return(AALL);
1398 return(AFAIL);
1400 return(AFAIL);
1403 /*******************************************************************
1404 check if the share mode on a file allows it to be deleted or unlinked
1405 return True if sharing doesn't prevent the operation
1406 ********************************************************************/
1407 BOOL check_file_sharing(int cnum,char *fname)
1409 int i;
1410 int ret = False;
1411 min_share_mode_entry *old_shares = 0;
1412 int num_share_modes;
1413 struct stat sbuf;
1414 share_lock_token token;
1415 int pid = getpid();
1417 if(!lp_share_modes(SNUM(cnum)))
1418 return True;
1420 if (stat(fname,&sbuf) == -1) return(True);
1422 lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token);
1423 num_share_modes = get_share_modes(cnum, token,
1424 (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares);
1426 for( i = 0; i < num_share_modes; i++)
1428 if (old_shares[i].share_mode != DENY_DOS)
1429 goto free_and_exit;
1431 if(old_shares[i].pid != pid)
1432 goto free_and_exit;
1435 /* XXXX exactly what share mode combinations should be allowed for
1436 deleting/renaming? */
1437 /* If we got here then either there were no share modes or
1438 all share modes were DENY_DOS and the pid == getpid() */
1439 ret = True;
1441 free_and_exit:
1443 unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token);
1444 if(old_shares != NULL)
1445 free((char *)old_shares);
1446 return(ret);
1449 /****************************************************************************
1450 C. Hoch 11/22/95
1451 Helper for open_file_shared.
1452 Truncate a file after checking locking; close file if locked.
1453 **************************************************************************/
1454 static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
1455 BOOL *share_locked)
1457 if (Files[fnum].can_write){
1458 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1459 /* If share modes are in force for this connection we
1460 have the share entry locked. Unlock it before closing. */
1461 if (*share_locked && lp_share_modes(SNUM(cnum)))
1462 unlock_share_entry( cnum, Files[fnum].fd_ptr->dev,
1463 Files[fnum].fd_ptr->inode, token);
1464 close_file(fnum);
1465 /* Share mode no longer locked. */
1466 *share_locked = False;
1467 errno = EACCES;
1468 unix_ERR_class = ERRDOS;
1469 unix_ERR_code = ERRlock;
1471 else
1472 ftruncate(Files[fnum].fd_ptr->fd,0);
1477 /****************************************************************************
1478 open a file with a share mode
1479 ****************************************************************************/
1480 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1481 int mode,int *Access,int *action)
1483 files_struct *fs_p = &Files[fnum];
1484 int flags=0;
1485 int flags2=0;
1486 int deny_mode = (share_mode>>4)&7;
1487 struct stat sbuf;
1488 BOOL file_existed = file_exist(fname,&sbuf);
1489 BOOL share_locked = False;
1490 BOOL fcbopen = False;
1491 share_lock_token token;
1492 uint32 dev = 0;
1493 uint32 inode = 0;
1495 fs_p->open = False;
1496 fs_p->fd_ptr = 0;
1498 /* this is for OS/2 EAs - try and say we don't support them */
1499 if (strstr(fname,".+,;=[]."))
1501 unix_ERR_class = ERRDOS;
1502 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1503 return;
1506 if ((ofun & 0x3) == 0 && file_existed)
1508 errno = EEXIST;
1509 return;
1512 if (ofun & 0x10)
1513 flags2 |= O_CREAT;
1514 if ((ofun & 0x3) == 2)
1515 flags2 |= O_TRUNC;
1517 /* note that we ignore the append flag as
1518 append does not mean the same thing under dos and unix */
1520 switch (share_mode&0xF)
1522 case 1:
1523 flags = O_WRONLY;
1524 break;
1525 case 0xF:
1526 fcbopen = True;
1527 flags = O_RDWR;
1528 break;
1529 case 2:
1530 flags = O_RDWR;
1531 break;
1532 default:
1533 flags = O_RDONLY;
1534 break;
1537 if (flags != O_RDONLY && file_existed &&
1538 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf))))
1540 if (!fcbopen)
1542 errno = EACCES;
1543 return;
1545 flags = O_RDONLY;
1548 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB)
1550 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1551 errno = EINVAL;
1552 return;
1555 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1557 if (lp_share_modes(SNUM(cnum)))
1559 int num_shares = 0;
1560 int i;
1561 min_share_mode_entry *old_shares = 0;
1564 if (file_existed)
1566 dev = (uint32)sbuf.st_dev;
1567 inode = (uint32)sbuf.st_ino;
1568 lock_share_entry(cnum, dev, inode, &token);
1569 share_locked = True;
1570 num_shares = get_share_modes(cnum, token, dev, inode, &old_shares);
1573 for(i = 0; i < num_shares; i++)
1575 /* someone else has a share lock on it, check to see
1576 if we can too */
1577 int old_open_mode = old_shares[i].share_mode &0xF;
1578 int old_deny_mode = (old_shares[i].share_mode >>4)&7;
1580 if (old_deny_mode > 4 || old_open_mode > 2)
1582 DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
1583 deny_mode,old_deny_mode,old_open_mode,fname));
1584 free((char *)old_shares);
1585 if(share_locked)
1586 unlock_share_entry(cnum, dev, inode, token);
1587 errno = EACCES;
1588 unix_ERR_class = ERRDOS;
1589 unix_ERR_code = ERRbadshare;
1590 return;
1594 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1595 old_shares[i].pid,fname);
1597 if ((access_allowed == AFAIL) ||
1598 (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
1599 (access_allowed == AREAD && flags == O_WRONLY) ||
1600 (access_allowed == AWRITE && flags == O_RDONLY))
1602 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1603 deny_mode,old_deny_mode,old_open_mode,
1604 old_shares[i].pid,fname,
1605 access_allowed));
1606 free((char *)old_shares);
1607 if(share_locked)
1608 unlock_share_entry(cnum, dev, inode, token);
1609 errno = EACCES;
1610 unix_ERR_class = ERRDOS;
1611 unix_ERR_code = ERRbadshare;
1612 return;
1615 if (access_allowed == AREAD)
1616 flags = O_RDONLY;
1618 if (access_allowed == AWRITE)
1619 flags = O_WRONLY;
1622 if(old_shares != 0)
1623 free((char *)old_shares);
1626 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1627 flags,flags2,mode));
1629 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1630 if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
1632 flags = O_RDONLY;
1633 open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1636 if (fs_p->open)
1638 int open_mode=0;
1640 if((share_locked == False) && lp_share_modes(SNUM(cnum)))
1642 /* We created the file - thus we must now lock the share entry before creating it. */
1643 dev = fs_p->fd_ptr->dev;
1644 inode = fs_p->fd_ptr->inode;
1645 lock_share_entry(cnum, dev, inode, &token);
1646 share_locked = True;
1649 switch (flags)
1651 case O_RDONLY:
1652 open_mode = 0;
1653 break;
1654 case O_RDWR:
1655 open_mode = 2;
1656 break;
1657 case O_WRONLY:
1658 open_mode = 1;
1659 break;
1662 fs_p->share_mode = (deny_mode<<4) | open_mode;
1664 if (Access)
1665 (*Access) = open_mode;
1667 if (action)
1669 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1670 if (!file_existed) *action = 2;
1671 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1673 /* We must create the share mode entry before truncate as
1674 truncate can fail due to locking and have to close the
1675 file (which expects the share_mode_entry to be there).
1677 if (lp_share_modes(SNUM(cnum)))
1678 set_share_mode(token, fnum);
1680 if ((flags2&O_TRUNC) && file_existed)
1681 truncate_unless_locked(fnum,cnum,token,&share_locked);
1684 if (share_locked && lp_share_modes(SNUM(cnum)))
1685 unlock_share_entry( cnum, dev, inode, token);
1688 /****************************************************************************
1689 seek a file. Try to avoid the seek if possible
1690 ****************************************************************************/
1691 int seek_file(int fnum,int pos)
1693 int offset = 0;
1694 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1695 offset = 3;
1697 Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset;
1698 return(Files[fnum].pos);
1701 /****************************************************************************
1702 read from a file
1703 ****************************************************************************/
1704 int read_file(int fnum,char *data,int pos,int n)
1706 int ret=0,readret;
1708 if (!Files[fnum].can_write)
1710 ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1712 data += ret;
1713 n -= ret;
1714 pos += ret;
1717 #if USE_MMAP
1718 if (Files[fnum].mmap_ptr)
1720 int num = MIN(n,Files[fnum].mmap_size-pos);
1721 if (num > 0)
1723 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1724 data += num;
1725 pos += num;
1726 n -= num;
1727 ret += num;
1730 #endif
1732 if (n <= 0)
1733 return(ret);
1735 if (seek_file(fnum,pos) != pos)
1737 DEBUG(3,("Failed to seek to %d\n",pos));
1738 return(ret);
1741 if (n > 0) {
1742 readret = read(Files[fnum].fd_ptr->fd,data,n);
1743 if (readret > 0) ret += readret;
1746 return(ret);
1750 /****************************************************************************
1751 write to a file
1752 ****************************************************************************/
1753 int write_file(int fnum,char *data,int n)
1755 if (!Files[fnum].can_write) {
1756 errno = EPERM;
1757 return(0);
1760 if (!Files[fnum].modified) {
1761 struct stat st;
1762 Files[fnum].modified = True;
1763 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1764 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1765 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1766 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1771 return(write_data(Files[fnum].fd_ptr->fd,data,n));
1775 /****************************************************************************
1776 load parameters specific to a connection/service
1777 ****************************************************************************/
1778 BOOL become_service(int cnum,BOOL do_chdir)
1780 extern char magic_char;
1781 static int last_cnum = -1;
1782 int snum;
1784 if (!OPEN_CNUM(cnum))
1786 last_cnum = -1;
1787 return(False);
1790 Connections[cnum].lastused = smb_last_time;
1792 snum = SNUM(cnum);
1794 if (do_chdir &&
1795 ChDir(Connections[cnum].connectpath) != 0 &&
1796 ChDir(Connections[cnum].origpath) != 0)
1798 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1799 Connections[cnum].connectpath,cnum));
1800 return(False);
1803 if (cnum == last_cnum)
1804 return(True);
1806 last_cnum = cnum;
1808 case_default = lp_defaultcase(snum);
1809 case_preserve = lp_preservecase(snum);
1810 short_case_preserve = lp_shortpreservecase(snum);
1811 case_mangle = lp_casemangle(snum);
1812 case_sensitive = lp_casesensitive(snum);
1813 magic_char = lp_magicchar(snum);
1814 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1815 return(True);
1819 /****************************************************************************
1820 find a service entry
1821 ****************************************************************************/
1822 int find_service(char *service)
1824 int iService;
1826 string_sub(service,"\\","/");
1828 iService = lp_servicenumber(service);
1830 /* now handle the special case of a home directory */
1831 if (iService < 0)
1833 char *phome_dir = get_home_dir(service);
1834 DEBUG(3,("checking for home directory %s gave %s\n",service,
1835 phome_dir?phome_dir:"(NULL)"));
1836 if (phome_dir)
1838 int iHomeService;
1839 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1841 lp_add_home(service,iHomeService,phome_dir);
1842 iService = lp_servicenumber(service);
1847 /* If we still don't have a service, attempt to add it as a printer. */
1848 if (iService < 0)
1850 int iPrinterService;
1852 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1854 char *pszTemp;
1856 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1857 pszTemp = PRINTCAP;
1858 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1860 DEBUG(3,("%s is a valid printer name\n", service));
1861 DEBUG(3,("adding %s as a printer service\n", service));
1862 lp_add_printer(service,iPrinterService);
1863 iService = lp_servicenumber(service);
1864 if (iService < 0)
1865 DEBUG(0,("failed to add %s as a printer service!\n", service));
1867 else
1868 DEBUG(3,("%s is not a valid printer name\n", service));
1872 /* just possibly it's a default service? */
1873 if (iService < 0)
1875 char *defservice = lp_defaultservice();
1876 if (defservice && *defservice && !strequal(defservice,service)) {
1877 iService = find_service(defservice);
1878 if (iService >= 0) {
1879 string_sub(service,"_","/");
1880 iService = lp_add_service(service,iService);
1885 if (iService >= 0)
1886 if (!VALID_SNUM(iService))
1888 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1889 iService = -1;
1892 if (iService < 0)
1893 DEBUG(3,("find_service() failed to find service %s\n", service));
1895 return (iService);
1899 /****************************************************************************
1900 create an error packet from a cached error.
1901 ****************************************************************************/
1902 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1904 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1906 int32 eclass = wbmpx->wr_errclass;
1907 int32 err = wbmpx->wr_error;
1909 /* We can now delete the auxiliary struct */
1910 free((char *)wbmpx);
1911 Files[fnum].wbmpx_ptr = NULL;
1912 return error_packet(inbuf,outbuf,eclass,err,line);
1916 struct
1918 int unixerror;
1919 int smbclass;
1920 int smbcode;
1921 } unix_smb_errmap[] =
1923 {EPERM,ERRDOS,ERRnoaccess},
1924 {EACCES,ERRDOS,ERRnoaccess},
1925 {ENOENT,ERRDOS,ERRbadfile},
1926 {EIO,ERRHRD,ERRgeneral},
1927 {EBADF,ERRSRV,ERRsrverror},
1928 {EINVAL,ERRSRV,ERRsrverror},
1929 {EEXIST,ERRDOS,ERRfilexists},
1930 {ENFILE,ERRDOS,ERRnofids},
1931 {EMFILE,ERRDOS,ERRnofids},
1932 {ENOSPC,ERRHRD,ERRdiskfull},
1933 #ifdef EDQUOT
1934 {EDQUOT,ERRHRD,ERRdiskfull},
1935 #endif
1936 #ifdef ENOTEMPTY
1937 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1938 #endif
1939 #ifdef EXDEV
1940 {EXDEV,ERRDOS,ERRdiffdevice},
1941 #endif
1942 {EROFS,ERRHRD,ERRnowrite},
1943 {0,0,0}
1947 /****************************************************************************
1948 create an error packet from errno
1949 ****************************************************************************/
1950 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1952 int eclass=def_class;
1953 int ecode=def_code;
1954 int i=0;
1956 if (unix_ERR_class != SUCCESS)
1958 eclass = unix_ERR_class;
1959 ecode = unix_ERR_code;
1960 unix_ERR_class = SUCCESS;
1961 unix_ERR_code = 0;
1963 else
1965 while (unix_smb_errmap[i].smbclass != 0)
1967 if (unix_smb_errmap[i].unixerror == errno)
1969 eclass = unix_smb_errmap[i].smbclass;
1970 ecode = unix_smb_errmap[i].smbcode;
1971 break;
1973 i++;
1977 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1981 /****************************************************************************
1982 create an error packet. Normally called using the ERROR() macro
1983 ****************************************************************************/
1984 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1986 int outsize = set_message(outbuf,0,0,True);
1987 int cmd;
1988 cmd = CVAL(inbuf,smb_com);
1990 CVAL(outbuf,smb_rcls) = error_class;
1991 SSVAL(outbuf,smb_err,error_code);
1993 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1994 timestring(),
1995 line,
1996 (int)CVAL(inbuf,smb_com),
1997 smb_fn_name(CVAL(inbuf,smb_com)),
1998 error_class,
1999 error_code));
2001 if (errno != 0)
2002 DEBUG(3,("error string = %s\n",strerror(errno)));
2004 return(outsize);
2008 #ifndef SIGCLD_IGNORE
2009 /****************************************************************************
2010 this prevents zombie child processes
2011 ****************************************************************************/
2012 static int sig_cld()
2014 static int depth = 0;
2015 if (depth != 0)
2017 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2018 depth=0;
2019 return(0);
2021 depth++;
2023 BlockSignals(True,SIGCLD);
2024 DEBUG(5,("got SIGCLD\n"));
2026 #ifdef USE_WAITPID
2027 while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2028 #endif
2030 /* Stop zombies */
2031 /* Stevens, Adv. Unix Prog. says that on system V you must call
2032 wait before reinstalling the signal handler, because the kernel
2033 calls the handler from within the signal-call when there is a
2034 child that has exited. This would lead to an infinite recursion
2035 if done vice versa. */
2037 #ifndef DONT_REINSTALL_SIG
2038 #ifdef SIGCLD_IGNORE
2039 signal(SIGCLD, SIG_IGN);
2040 #else
2041 signal(SIGCLD, SIGNAL_CAST sig_cld);
2042 #endif
2043 #endif
2045 #ifndef USE_WAITPID
2046 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
2047 #endif
2048 depth--;
2049 BlockSignals(False,SIGCLD);
2050 return 0;
2052 #endif
2054 /****************************************************************************
2055 this is called when the client exits abruptly
2056 **************************************************************************/
2057 static int sig_pipe()
2059 extern int password_client;
2060 BlockSignals(True,SIGPIPE);
2062 if (password_client != -1) {
2063 DEBUG(3,("lost connection to password server\n"));
2064 close(password_client);
2065 password_client = -1;
2066 #ifndef DONT_REINSTALL_SIG
2067 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2068 #endif
2069 BlockSignals(False,SIGPIPE);
2070 return 0;
2073 exit_server("Got sigpipe\n");
2074 return(0);
2077 /****************************************************************************
2078 open the socket communication
2079 ****************************************************************************/
2080 static BOOL open_sockets(BOOL is_daemon,int port)
2082 extern int Client;
2084 if (is_daemon)
2086 int s;
2087 struct sockaddr addr;
2088 int in_addrlen = sizeof(addr);
2090 /* Stop zombies */
2091 #ifdef SIGCLD_IGNORE
2092 signal(SIGCLD, SIG_IGN);
2093 #else
2094 signal(SIGCLD, SIGNAL_CAST sig_cld);
2095 #endif
2097 /* open an incoming socket */
2098 s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
2099 if (s == -1)
2100 return(False);
2102 /* ready to listen */
2103 if (listen(s, 5) == -1)
2105 DEBUG(0,("listen: %s\n",strerror(errno)));
2106 close(s);
2107 return False;
2110 if(atexit_set == 0)
2111 atexit(killkids);
2113 /* now accept incoming connections - forking a new process
2114 for each incoming connection */
2115 DEBUG(2,("waiting for a connection\n"));
2116 while (1)
2118 Client = accept(s,&addr,&in_addrlen);
2120 if (Client == -1 && errno == EINTR)
2121 continue;
2123 if (Client == -1)
2125 DEBUG(0,("accept: %s\n",strerror(errno)));
2126 continue;
2129 #ifdef NO_FORK_DEBUG
2130 #ifndef NO_SIGNAL_TEST
2131 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2132 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2133 #endif
2134 return True;
2135 #else
2136 if (Client != -1 && fork()==0)
2138 /* Child code ... */
2139 #ifndef NO_SIGNAL_TEST
2140 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2141 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2142 #endif
2143 /* close the listening socket */
2144 close(s);
2146 /* close our standard file descriptors */
2147 close_low_fds();
2148 am_parent = 0;
2150 set_socket_options(Client,"SO_KEEPALIVE");
2151 set_socket_options(Client,user_socket_options);
2153 /* Reset global variables in util.c so that
2154 client substitutions will be done correctly
2155 in the process.
2157 reset_globals_after_fork();
2158 return True;
2160 close(Client); /* The parent doesn't need this socket */
2161 #endif
2164 else
2166 /* We will abort gracefully when the client or remote system
2167 goes away */
2168 #ifndef NO_SIGNAL_TEST
2169 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2170 #endif
2171 Client = dup(0);
2173 /* close our standard file descriptors */
2174 close_low_fds();
2176 set_socket_options(Client,"SO_KEEPALIVE");
2177 set_socket_options(Client,user_socket_options);
2180 return True;
2184 /****************************************************************************
2185 check if a snum is in use
2186 ****************************************************************************/
2187 BOOL snum_used(int snum)
2189 int i;
2190 for (i=0;i<MAX_CONNECTIONS;i++)
2191 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2192 return(True);
2193 return(False);
2196 /****************************************************************************
2197 reload the services file
2198 **************************************************************************/
2199 BOOL reload_services(BOOL test)
2201 BOOL ret;
2203 if (lp_loaded())
2205 pstring fname;
2206 strcpy(fname,lp_configfile());
2207 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2209 strcpy(servicesf,fname);
2210 test = False;
2214 reopen_logs();
2216 if (test && !lp_file_list_changed())
2217 return(True);
2219 lp_killunused(snum_used);
2221 ret = lp_load(servicesf,False);
2223 /* perhaps the config filename is now set */
2224 if (!test)
2225 reload_services(True);
2227 reopen_logs();
2229 load_interfaces();
2232 extern int Client;
2233 if (Client != -1) {
2234 set_socket_options(Client,"SO_KEEPALIVE");
2235 set_socket_options(Client,user_socket_options);
2239 create_mangled_stack(lp_mangledstack());
2241 /* this forces service parameters to be flushed */
2242 become_service(-1,True);
2244 return(ret);
2249 /****************************************************************************
2250 this prevents zombie child processes
2251 ****************************************************************************/
2252 static int sig_hup()
2254 BlockSignals(True,SIGHUP);
2255 DEBUG(0,("Got SIGHUP\n"));
2256 reload_services(False);
2257 #ifndef DONT_REINSTALL_SIG
2258 signal(SIGHUP,SIGNAL_CAST sig_hup);
2259 #endif
2260 BlockSignals(False,SIGHUP);
2261 return(0);
2264 /****************************************************************************
2265 Setup the groups a user belongs to.
2266 ****************************************************************************/
2267 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
2268 int **p_igroups, gid_t **p_groups)
2270 if (-1 == initgroups(user,gid))
2272 if (getuid() == 0)
2274 DEBUG(0,("Unable to initgroups!\n"));
2275 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2276 DEBUG(0,("This is probably a problem with the account %s\n",user));
2279 else
2281 int i,ngroups;
2282 int *igroups;
2283 gid_t grp = 0;
2284 ngroups = getgroups(0,&grp);
2285 if (ngroups <= 0)
2286 ngroups = 32;
2287 igroups = (int *)malloc(sizeof(int)*ngroups);
2288 for (i=0;i<ngroups;i++)
2289 igroups[i] = 0x42424242;
2290 ngroups = getgroups(ngroups,(gid_t *)igroups);
2292 if (igroups[0] == 0x42424242)
2293 ngroups = 0;
2295 *p_ngroups = ngroups;
2297 /* The following bit of code is very strange. It is due to the
2298 fact that some OSes use int* and some use gid_t* for
2299 getgroups, and some (like SunOS) use both, one in prototypes,
2300 and one in man pages and the actual code. Thus we detect it
2301 dynamically using some very ugly code */
2302 if (ngroups > 0)
2304 /* does getgroups return ints or gid_t ?? */
2305 static BOOL groups_use_ints = True;
2307 if (groups_use_ints &&
2308 ngroups == 1 &&
2309 SVAL(igroups,2) == 0x4242)
2310 groups_use_ints = False;
2312 for (i=0;groups_use_ints && i<ngroups;i++)
2313 if (igroups[i] == 0x42424242)
2314 groups_use_ints = False;
2316 if (groups_use_ints)
2318 *p_igroups = igroups;
2319 *p_groups = (gid_t *)igroups;
2321 else
2323 gid_t *groups = (gid_t *)igroups;
2324 igroups = (int *)malloc(sizeof(int)*ngroups);
2325 for (i=0;i<ngroups;i++)
2326 igroups[i] = groups[i];
2327 *p_igroups = igroups;
2328 *p_groups = (gid_t *)groups;
2331 DEBUG(3,("%s is in %d groups\n",user,ngroups));
2332 for (i=0;i<ngroups;i++)
2333 DEBUG(3,("%d ",igroups[i]));
2334 DEBUG(3,("\n"));
2336 return 0;
2339 /****************************************************************************
2340 make a connection to a service
2341 ****************************************************************************/
2342 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2344 int cnum;
2345 int snum;
2346 struct passwd *pass = NULL;
2347 connection_struct *pcon;
2348 BOOL guest = False;
2349 BOOL force = False;
2350 static BOOL first_connection = True;
2352 strlower(service);
2354 snum = find_service(service);
2355 if (snum < 0)
2357 if (strequal(service,"IPC$"))
2359 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2360 return(-3);
2363 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2364 return(-2);
2367 if (strequal(service,HOMES_NAME))
2369 if (*user && Get_Pwnam(user,True))
2370 return(make_connection(user,user,password,pwlen,dev,vuid));
2372 if (validated_username(vuid))
2374 strcpy(user,validated_username(vuid));
2375 return(make_connection(user,user,password,pwlen,dev,vuid));
2379 if (!lp_snum_ok(snum) || !check_access(snum)) {
2380 return(-4);
2383 /* you can only connect to the IPC$ service as an ipc device */
2384 if (strequal(service,"IPC$"))
2385 strcpy(dev,"IPC");
2387 if (*dev == '?' || !*dev)
2389 if (lp_print_ok(snum))
2390 strcpy(dev,"LPT1:");
2391 else
2392 strcpy(dev,"A:");
2395 /* if the request is as a printer and you can't print then refuse */
2396 strupper(dev);
2397 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2398 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2399 return(-6);
2402 /* lowercase the user name */
2403 strlower(user);
2405 /* add it as a possible user name */
2406 add_session_user(service);
2408 /* shall we let them in? */
2409 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2411 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2412 return(-1);
2415 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2416 if (cnum < 0)
2418 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2419 return(-1);
2422 pcon = &Connections[cnum];
2423 bzero((char *)pcon,sizeof(*pcon));
2425 /* find out some info about the user */
2426 pass = Get_Pwnam(user,True);
2428 if (pass == NULL)
2430 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2431 return(-7);
2434 pcon->read_only = lp_readonly(snum);
2437 pstring list;
2438 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2439 string_sub(list,"%S",service);
2441 if (user_in_list(user,list))
2442 pcon->read_only = True;
2444 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2445 string_sub(list,"%S",service);
2447 if (user_in_list(user,list))
2448 pcon->read_only = False;
2451 /* admin user check */
2452 if (user_in_list(user,lp_admin_users(snum)) &&
2453 !pcon->read_only)
2455 pcon->admin_user = True;
2456 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2458 else
2459 pcon->admin_user = False;
2461 pcon->force_user = force;
2462 pcon->vuid = vuid;
2463 pcon->uid = pass->pw_uid;
2464 pcon->gid = pass->pw_gid;
2465 pcon->num_files_open = 0;
2466 pcon->lastused = time(NULL);
2467 pcon->service = snum;
2468 pcon->used = True;
2469 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2470 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2471 pcon->dirptr = NULL;
2472 string_set(&pcon->dirpath,"");
2473 string_set(&pcon->user,user);
2475 #if HAVE_GETGRNAM
2476 if (*lp_force_group(snum))
2478 struct group *gptr;
2479 pstring gname;
2481 StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2482 /* default service may be a group name */
2483 string_sub(gname,"%S",service);
2484 gptr = (struct group *)getgrnam(gname);
2486 if (gptr)
2488 pcon->gid = gptr->gr_gid;
2489 DEBUG(3,("Forced group %s\n",gname));
2491 else
2492 DEBUG(1,("Couldn't find group %s\n",gname));
2494 #endif
2496 if (*lp_force_user(snum))
2498 struct passwd *pass2;
2499 fstring fuser;
2500 strcpy(fuser,lp_force_user(snum));
2501 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2502 if (pass2)
2504 pcon->uid = pass2->pw_uid;
2505 string_set(&pcon->user,fuser);
2506 strcpy(user,fuser);
2507 pcon->force_user = True;
2508 DEBUG(3,("Forced user %s\n",fuser));
2510 else
2511 DEBUG(1,("Couldn't find user %s\n",fuser));
2515 pstring s;
2516 strcpy(s,lp_pathname(snum));
2517 standard_sub(cnum,s);
2518 string_set(&pcon->connectpath,s);
2519 DEBUG(3,("Connect path is %s\n",s));
2522 /* groups stuff added by ih */
2523 pcon->ngroups = 0;
2524 pcon->groups = NULL;
2526 if (!IS_IPC(cnum))
2528 /* Find all the groups this uid is in and store them. Used by become_user() */
2529 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2531 /* check number of connections */
2532 if (!claim_connection(cnum,
2533 lp_servicename(SNUM(cnum)),
2534 lp_max_connections(SNUM(cnum)),False))
2536 DEBUG(1,("too many connections - rejected\n"));
2537 return(-8);
2540 if (lp_status(SNUM(cnum)))
2541 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2543 first_connection = False;
2544 } /* IS_IPC */
2546 pcon->open = True;
2548 /* execute any "root preexec = " line */
2549 if (*lp_rootpreexec(SNUM(cnum)))
2551 pstring cmd;
2552 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2553 standard_sub(cnum,cmd);
2554 DEBUG(5,("cmd=%s\n",cmd));
2555 smbrun(cmd,NULL,False);
2558 if (!become_user(cnum,pcon->vuid))
2560 DEBUG(0,("Can't become connected user!\n"));
2561 pcon->open = False;
2562 if (!IS_IPC(cnum)) {
2563 yield_connection(cnum,
2564 lp_servicename(SNUM(cnum)),
2565 lp_max_connections(SNUM(cnum)));
2566 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2568 return(-1);
2571 if (ChDir(pcon->connectpath) != 0)
2573 DEBUG(0,("Can't change directory to %s (%s)\n",
2574 pcon->connectpath,strerror(errno)));
2575 pcon->open = False;
2576 unbecome_user();
2577 if (!IS_IPC(cnum)) {
2578 yield_connection(cnum,
2579 lp_servicename(SNUM(cnum)),
2580 lp_max_connections(SNUM(cnum)));
2581 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2583 return(-5);
2586 string_set(&pcon->origpath,pcon->connectpath);
2588 #if SOFTLINK_OPTIMISATION
2589 /* resolve any soft links early */
2591 pstring s;
2592 strcpy(s,pcon->connectpath);
2593 GetWd(s);
2594 string_set(&pcon->connectpath,s);
2595 ChDir(pcon->connectpath);
2597 #endif
2599 num_connections_open++;
2600 add_session_user(user);
2602 /* execute any "preexec = " line */
2603 if (*lp_preexec(SNUM(cnum)))
2605 pstring cmd;
2606 strcpy(cmd,lp_preexec(SNUM(cnum)));
2607 standard_sub(cnum,cmd);
2608 smbrun(cmd,NULL,False);
2611 /* we've finished with the sensitive stuff */
2612 unbecome_user();
2615 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2616 timestring(),
2617 remote_machine,
2618 client_addr(),
2619 lp_servicename(SNUM(cnum)),user,
2620 pcon->uid,
2621 pcon->gid,
2622 (int)getpid()));
2625 return(cnum);
2629 /****************************************************************************
2630 find first available file slot
2631 ****************************************************************************/
2632 int find_free_file(void )
2634 int i;
2635 /* we start at 1 here for an obscure reason I can't now remember,
2636 but I think is important :-) */
2637 for (i=1;i<MAX_OPEN_FILES;i++)
2638 if (!Files[i].open)
2639 return(i);
2640 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2641 return(-1);
2644 /****************************************************************************
2645 find first available connection slot, starting from a random position.
2646 The randomisation stops problems with the server dieing and clients
2647 thinking the server is still available.
2648 ****************************************************************************/
2649 static int find_free_connection(int hash )
2651 int i;
2652 BOOL used=False;
2653 hash = (hash % (MAX_CONNECTIONS-2))+1;
2655 again:
2657 for (i=hash+1;i!=hash;)
2659 if (!Connections[i].open && Connections[i].used == used)
2661 DEBUG(3,("found free connection number %d\n",i));
2662 return(i);
2664 i++;
2665 if (i == MAX_CONNECTIONS)
2666 i = 1;
2669 if (!used)
2671 used = !used;
2672 goto again;
2675 DEBUG(1,("ERROR! Out of connection structures\n"));
2676 return(-1);
2680 /****************************************************************************
2681 reply for the core protocol
2682 ****************************************************************************/
2683 int reply_corep(char *outbuf)
2685 int outsize = set_message(outbuf,1,0,True);
2687 Protocol = PROTOCOL_CORE;
2689 return outsize;
2693 /****************************************************************************
2694 reply for the coreplus protocol
2695 ****************************************************************************/
2696 int reply_coreplus(char *outbuf)
2698 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2699 int outsize = set_message(outbuf,13,0,True);
2700 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2701 readbraw and writebraw (possibly) */
2702 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2703 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2705 Protocol = PROTOCOL_COREPLUS;
2707 return outsize;
2711 /****************************************************************************
2712 reply for the lanman 1.0 protocol
2713 ****************************************************************************/
2714 int reply_lanman1(char *outbuf)
2716 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2717 int secword=0;
2718 BOOL doencrypt = SMBENCRYPT();
2719 time_t t = time(NULL);
2720 /* We need to save and restore this as it can be destroyed
2721 if we call another server if security=server
2722 Thanks to Paul Nelson @ Thursby for pointing this out.
2724 uint16 mid = SVAL(outbuf, smb_mid);
2726 if (lp_security()>=SEC_USER) secword |= 1;
2727 if (doencrypt) secword |= 2;
2729 set_message(outbuf,13,doencrypt?8:0,True);
2730 SSVAL(outbuf,smb_vwv1,secword);
2731 #ifdef SMB_PASSWD
2732 /* Create a token value and add it to the outgoing packet. */
2733 if (doencrypt)
2734 generate_next_challenge(smb_buf(outbuf));
2735 #endif
2737 Protocol = PROTOCOL_LANMAN1;
2739 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2740 DEBUG(3,("using password server validation\n"));
2741 #ifdef SMB_PASSWD
2742 if (doencrypt) set_challenge(smb_buf(outbuf));
2743 #endif
2746 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2747 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2748 SSVAL(outbuf,smb_vwv2,max_recv);
2749 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2750 SSVAL(outbuf,smb_vwv4,1);
2751 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2752 readbraw writebraw (possibly) */
2753 SIVAL(outbuf,smb_vwv6,getpid());
2754 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2756 put_dos_date(outbuf,smb_vwv8,t);
2758 return (smb_len(outbuf)+4);
2762 /****************************************************************************
2763 reply for the lanman 2.0 protocol
2764 ****************************************************************************/
2765 int reply_lanman2(char *outbuf)
2767 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2768 int secword=0;
2769 BOOL doencrypt = SMBENCRYPT();
2770 time_t t = time(NULL);
2771 /* We need to save and restore this as it can be destroyed
2772 if we call another server if security=server
2773 Thanks to Paul Nelson @ Thursby for pointing this out.
2775 uint16 mid = SVAL(outbuf, smb_mid);
2777 if (lp_security()>=SEC_USER) secword |= 1;
2778 if (doencrypt) secword |= 2;
2780 set_message(outbuf,13,doencrypt?8:0,True);
2781 SSVAL(outbuf,smb_vwv1,secword);
2782 #ifdef SMB_PASSWD
2783 /* Create a token value and add it to the outgoing packet. */
2784 if (doencrypt)
2785 generate_next_challenge(smb_buf(outbuf));
2786 #endif
2788 SIVAL(outbuf,smb_vwv6,getpid());
2790 Protocol = PROTOCOL_LANMAN2;
2792 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2793 DEBUG(3,("using password server validation\n"));
2794 #ifdef SMB_PASSWD
2795 if (doencrypt) set_challenge(smb_buf(outbuf));
2796 #endif
2799 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2800 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2801 SSVAL(outbuf,smb_vwv2,max_recv);
2802 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2803 SSVAL(outbuf,smb_vwv4,1);
2804 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2805 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2806 put_dos_date(outbuf,smb_vwv8,t);
2808 return (smb_len(outbuf)+4);
2812 /****************************************************************************
2813 reply for the nt protocol
2814 ****************************************************************************/
2815 int reply_nt1(char *outbuf)
2817 /* dual names + lock_and_read + nt SMBs + remote API calls */
2818 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
2820 other valid capabilities which we may support at some time...
2821 CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
2822 CAP_LARGE_FILES|CAP_LARGE_READX|
2823 CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
2826 int secword=0;
2827 BOOL doencrypt = SMBENCRYPT();
2828 time_t t = time(NULL);
2829 int data_len;
2830 int encrypt_len;
2831 char challenge_len = 8;
2832 /* We need to save and restore this as it can be destroyed
2833 if we call another server if security=server
2834 Thanks to Paul Nelson @ Thursby for pointing this out.
2836 uint16 mid = SVAL(outbuf, smb_mid);
2838 if (lp_readraw() && lp_writeraw())
2840 capabilities |= CAP_RAW_MODE;
2843 if (lp_security()>=SEC_USER) secword |= 1;
2844 if (doencrypt) secword |= 2;
2846 /* decide where (if) to put the encryption challenge, and
2847 follow it with the OEM'd domain name
2849 encrypt_len = doencrypt?challenge_len:0;
2850 #if UNICODE
2851 data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
2852 #else
2853 data_len = encrypt_len + strlen(myworkgroup) + 1;
2854 #endif
2856 set_message(outbuf,17,data_len,True);
2858 #if UNICODE
2859 /* put the OEM'd domain name */
2860 PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
2861 #else
2862 strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
2863 #endif
2865 CVAL(outbuf,smb_vwv1) = secword;
2866 #ifdef SMB_PASSWD
2867 /* Create a token value and add it to the outgoing packet. */
2868 if (doencrypt)
2870 generate_next_challenge(smb_buf(outbuf));
2872 /* Tell the nt machine how long the challenge is. */
2873 SSVALS(outbuf,smb_vwv16+1,challenge_len);
2875 #endif
2877 Protocol = PROTOCOL_NT1;
2879 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2880 DEBUG(3,("using password server validation\n"));
2881 #ifdef SMB_PASSWD
2882 if (doencrypt) set_challenge(smb_buf(outbuf));
2883 #endif
2886 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2887 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2888 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2889 SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
2890 SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
2891 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2892 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2893 put_long_date(outbuf+smb_vwv11+1,t);
2894 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2895 SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
2897 return (smb_len(outbuf)+4);
2900 /* these are the protocol lists used for auto architecture detection:
2902 WinNT 3.51:
2903 protocol [PC NETWORK PROGRAM 1.0]
2904 protocol [XENIX CORE]
2905 protocol [MICROSOFT NETWORKS 1.03]
2906 protocol [LANMAN1.0]
2907 protocol [Windows for Workgroups 3.1a]
2908 protocol [LM1.2X002]
2909 protocol [LANMAN2.1]
2910 protocol [NT LM 0.12]
2912 Win95:
2913 protocol [PC NETWORK PROGRAM 1.0]
2914 protocol [XENIX CORE]
2915 protocol [MICROSOFT NETWORKS 1.03]
2916 protocol [LANMAN1.0]
2917 protocol [Windows for Workgroups 3.1a]
2918 protocol [LM1.2X002]
2919 protocol [LANMAN2.1]
2920 protocol [NT LM 0.12]
2922 OS/2:
2923 protocol [PC NETWORK PROGRAM 1.0]
2924 protocol [XENIX CORE]
2925 protocol [LANMAN1.0]
2926 protocol [LM1.2X002]
2927 protocol [LANMAN2.1]
2931 * Modified to recognize the architecture of the remote machine better.
2933 * This appears to be the matrix of which protocol is used by which
2934 * MS product.
2935 Protocol WfWg Win95 WinNT OS/2
2936 PC NETWORK PROGRAM 1.0 1 1 1 1
2937 XENIX CORE 2 2
2938 MICROSOFT NETWORKS 3.0 2 2
2939 DOS LM1.2X002 3 3
2940 MICROSOFT NETWORKS 1.03 3
2941 DOS LANMAN2.1 4 4
2942 LANMAN1.0 4 3
2943 Windows for Workgroups 3.1a 5 5 5
2944 LM1.2X002 6 4
2945 LANMAN2.1 7 5
2946 NT LM 0.12 6 8
2948 * tim@fsg.com 09/29/95
2951 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2952 #define ARCH_WIN95 0x2
2953 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2954 #define ARCH_WINNT 0x8
2955 #define ARCH_SAMBA 0x10
2957 #define ARCH_ALL 0x1F
2959 /* List of supported protocols, most desired first */
2960 struct {
2961 char *proto_name;
2962 char *short_name;
2963 int (*proto_reply_fn)(char *);
2964 int protocol_level;
2965 } supported_protocols[] = {
2966 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2967 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2968 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2969 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2970 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2971 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2972 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2973 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2974 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2975 {NULL,NULL},
2979 /****************************************************************************
2980 reply to a negprot
2981 ****************************************************************************/
2982 static int reply_negprot(char *inbuf,char *outbuf)
2984 extern fstring remote_arch;
2985 int outsize = set_message(outbuf,1,0,True);
2986 int Index=0;
2987 int choice= -1;
2988 int protocol;
2989 char *p;
2990 int bcc = SVAL(smb_buf(inbuf),-2);
2991 int arch = ARCH_ALL;
2993 p = smb_buf(inbuf)+1;
2994 while (p < (smb_buf(inbuf) + bcc))
2996 Index++;
2997 DEBUG(3,("Requested protocol [%s]\n",p));
2998 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2999 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
3000 else if (strcsequal(p,"DOS LM1.2X002"))
3001 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3002 else if (strcsequal(p,"DOS LANMAN2.1"))
3003 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3004 else if (strcsequal(p,"NT LM 0.12"))
3005 arch &= ( ARCH_WIN95 | ARCH_WINNT );
3006 else if (strcsequal(p,"LANMAN2.1"))
3007 arch &= ( ARCH_WINNT | ARCH_OS2 );
3008 else if (strcsequal(p,"LM1.2X002"))
3009 arch &= ( ARCH_WINNT | ARCH_OS2 );
3010 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
3011 arch &= ARCH_WINNT;
3012 else if (strcsequal(p,"XENIX CORE"))
3013 arch &= ( ARCH_WINNT | ARCH_OS2 );
3014 else if (strcsequal(p,"Samba")) {
3015 arch = ARCH_SAMBA;
3016 break;
3019 p += strlen(p) + 2;
3022 switch ( arch ) {
3023 case ARCH_SAMBA:
3024 strcpy(remote_arch,"Samba");
3025 break;
3026 case ARCH_WFWG:
3027 strcpy(remote_arch,"WfWg");
3028 break;
3029 case ARCH_WIN95:
3030 strcpy(remote_arch,"Win95");
3031 break;
3032 case ARCH_WINNT:
3033 strcpy(remote_arch,"WinNT");
3034 break;
3035 case ARCH_OS2:
3036 strcpy(remote_arch,"OS2");
3037 break;
3038 default:
3039 strcpy(remote_arch,"UNKNOWN");
3040 break;
3043 /* possibly reload - change of architecture */
3044 reload_services(True);
3046 /* a special case to stop password server loops */
3047 if (Index == 1 && strequal(remote_machine,myhostname) &&
3048 lp_security()==SEC_SERVER)
3049 exit_server("Password server loop!");
3051 /* Check for protocols, most desirable first */
3052 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
3054 p = smb_buf(inbuf)+1;
3055 Index = 0;
3056 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
3057 while (p < (smb_buf(inbuf) + bcc))
3059 if (strequal(p,supported_protocols[protocol].proto_name))
3060 choice = Index;
3061 Index++;
3062 p += strlen(p) + 2;
3064 if(choice != -1)
3065 break;
3068 SSVAL(outbuf,smb_vwv0,choice);
3069 if(choice != -1) {
3070 extern fstring remote_proto;
3071 strcpy(remote_proto,supported_protocols[protocol].short_name);
3072 reload_services(True);
3073 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
3074 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
3076 else {
3077 DEBUG(0,("No protocol supported !\n"));
3079 SSVAL(outbuf,smb_vwv0,choice);
3081 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3083 return(outsize);
3087 /****************************************************************************
3088 close all open files for a connection
3089 ****************************************************************************/
3090 static void close_open_files(int cnum)
3092 int i;
3093 for (i=0;i<MAX_OPEN_FILES;i++)
3094 if( Files[i].cnum == cnum && Files[i].open) {
3095 close_file(i);
3101 /****************************************************************************
3102 close a cnum
3103 ****************************************************************************/
3104 void close_cnum(int cnum, uint16 vuid)
3106 DirCacheFlush(SNUM(cnum));
3108 unbecome_user();
3110 if (!OPEN_CNUM(cnum))
3112 DEBUG(0,("Can't close cnum %d\n",cnum));
3113 return;
3116 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3117 timestring(),
3118 remote_machine,client_addr(),
3119 lp_servicename(SNUM(cnum))));
3121 yield_connection(cnum,
3122 lp_servicename(SNUM(cnum)),
3123 lp_max_connections(SNUM(cnum)));
3125 if (lp_status(SNUM(cnum)))
3126 yield_connection(cnum,"STATUS.",MAXSTATUS);
3128 close_open_files(cnum);
3129 dptr_closecnum(cnum);
3131 /* execute any "postexec = " line */
3132 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
3134 pstring cmd;
3135 strcpy(cmd,lp_postexec(SNUM(cnum)));
3136 standard_sub(cnum,cmd);
3137 smbrun(cmd,NULL,False);
3138 unbecome_user();
3141 unbecome_user();
3142 /* execute any "root postexec = " line */
3143 if (*lp_rootpostexec(SNUM(cnum)))
3145 pstring cmd;
3146 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3147 standard_sub(cnum,cmd);
3148 smbrun(cmd,NULL,False);
3151 Connections[cnum].open = False;
3152 num_connections_open--;
3153 if (Connections[cnum].ngroups && Connections[cnum].groups)
3155 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3156 free(Connections[cnum].groups);
3157 free(Connections[cnum].igroups);
3158 Connections[cnum].groups = NULL;
3159 Connections[cnum].igroups = NULL;
3160 Connections[cnum].ngroups = 0;
3163 string_set(&Connections[cnum].user,"");
3164 string_set(&Connections[cnum].dirpath,"");
3165 string_set(&Connections[cnum].connectpath,"");
3169 /****************************************************************************
3170 simple routines to do connection counting
3171 ****************************************************************************/
3172 BOOL yield_connection(int cnum,char *name,int max_connections)
3174 struct connect_record crec;
3175 pstring fname;
3176 FILE *f;
3177 int mypid = getpid();
3178 int i;
3180 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3182 if (max_connections <= 0)
3183 return(True);
3185 bzero(&crec,sizeof(crec));
3187 strcpy(fname,lp_lockdir());
3188 standard_sub(cnum,fname);
3189 trim_string(fname,"","/");
3191 strcat(fname,"/");
3192 strcat(fname,name);
3193 strcat(fname,".LCK");
3195 f = fopen(fname,"r+");
3196 if (!f)
3198 DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
3199 return(False);
3202 fseek(f,0,SEEK_SET);
3204 /* find a free spot */
3205 for (i=0;i<max_connections;i++)
3207 if (fread(&crec,sizeof(crec),1,f) != 1)
3209 DEBUG(2,("Entry not found in lock file %s\n",fname));
3210 fclose(f);
3211 return(False);
3213 if (crec.pid == mypid && crec.cnum == cnum)
3214 break;
3217 if (crec.pid != mypid || crec.cnum != cnum)
3219 fclose(f);
3220 DEBUG(2,("Entry not found in lock file %s\n",fname));
3221 return(False);
3224 bzero((void *)&crec,sizeof(crec));
3226 /* remove our mark */
3227 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3228 fwrite(&crec,sizeof(crec),1,f) != 1)
3230 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3231 fclose(f);
3232 return(False);
3235 DEBUG(3,("Yield successful\n"));
3237 fclose(f);
3238 return(True);
3242 /****************************************************************************
3243 simple routines to do connection counting
3244 ****************************************************************************/
3245 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3247 struct connect_record crec;
3248 pstring fname;
3249 FILE *f;
3250 int snum = SNUM(cnum);
3251 int i,foundi= -1;
3252 int total_recs;
3254 if (max_connections <= 0)
3255 return(True);
3257 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3259 strcpy(fname,lp_lockdir());
3260 standard_sub(cnum,fname);
3261 trim_string(fname,"","/");
3263 if (!directory_exist(fname,NULL))
3264 mkdir(fname,0755);
3266 strcat(fname,"/");
3267 strcat(fname,name);
3268 strcat(fname,".LCK");
3270 if (!file_exist(fname,NULL))
3272 int oldmask = umask(022);
3273 f = fopen(fname,"w");
3274 if (f) fclose(f);
3275 umask(oldmask);
3278 total_recs = file_size(fname) / sizeof(crec);
3280 f = fopen(fname,"r+");
3282 if (!f)
3284 DEBUG(1,("couldn't open lock file %s\n",fname));
3285 return(False);
3288 /* find a free spot */
3289 for (i=0;i<max_connections;i++)
3292 if (i>=total_recs ||
3293 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3294 fread(&crec,sizeof(crec),1,f) != 1)
3296 if (foundi < 0) foundi = i;
3297 break;
3300 if (Clear && crec.pid && !process_exists(crec.pid))
3302 fseek(f,i*sizeof(crec),SEEK_SET);
3303 bzero((void *)&crec,sizeof(crec));
3304 fwrite(&crec,sizeof(crec),1,f);
3305 if (foundi < 0) foundi = i;
3306 continue;
3308 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3310 foundi=i;
3311 if (!Clear) break;
3315 if (foundi < 0)
3317 DEBUG(3,("no free locks in %s\n",fname));
3318 fclose(f);
3319 return(False);
3322 /* fill in the crec */
3323 bzero((void *)&crec,sizeof(crec));
3324 crec.magic = 0x280267;
3325 crec.pid = getpid();
3326 crec.cnum = cnum;
3327 crec.uid = Connections[cnum].uid;
3328 crec.gid = Connections[cnum].gid;
3329 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3330 crec.start = time(NULL);
3332 StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3333 StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3335 /* make our mark */
3336 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3337 fwrite(&crec,sizeof(crec),1,f) != 1)
3339 fclose(f);
3340 return(False);
3343 fclose(f);
3344 return(True);
3347 #if DUMP_CORE
3348 /*******************************************************************
3349 prepare to dump a core file - carefully!
3350 ********************************************************************/
3351 static BOOL dump_core(void)
3353 char *p;
3354 pstring dname;
3355 strcpy(dname,debugf);
3356 if ((p=strrchr(dname,'/'))) *p=0;
3357 strcat(dname,"/corefiles");
3358 mkdir(dname,0700);
3359 sys_chown(dname,getuid(),getgid());
3360 chmod(dname,0700);
3361 if (chdir(dname)) return(False);
3362 umask(~(0700));
3364 #ifndef NO_GETRLIMIT
3365 #ifdef RLIMIT_CORE
3367 struct rlimit rlp;
3368 getrlimit(RLIMIT_CORE, &rlp);
3369 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3370 setrlimit(RLIMIT_CORE, &rlp);
3371 getrlimit(RLIMIT_CORE, &rlp);
3372 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3374 #endif
3375 #endif
3378 DEBUG(0,("Dumping core in %s\n",dname));
3379 return(True);
3381 #endif
3383 /****************************************************************************
3384 exit the server
3385 ****************************************************************************/
3386 void exit_server(char *reason)
3388 static int firsttime=1;
3389 int i;
3391 if (!firsttime) exit(0);
3392 firsttime = 0;
3394 unbecome_user();
3395 DEBUG(2,("Closing connections\n"));
3396 for (i=0;i<MAX_CONNECTIONS;i++)
3397 if (Connections[i].open)
3398 close_cnum(i,-1);
3399 #ifdef DFS_AUTH
3400 if (dcelogin_atmost_once)
3401 dfs_unlogin();
3402 #endif
3403 if (!reason) {
3404 int oldlevel = DEBUGLEVEL;
3405 DEBUGLEVEL = 10;
3406 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3407 if (last_inbuf)
3408 show_msg(last_inbuf);
3409 DEBUGLEVEL = oldlevel;
3410 DEBUG(0,("===============================================================\n"));
3411 #if DUMP_CORE
3412 if (dump_core()) return;
3413 #endif
3416 #ifdef FAST_SHARE_MODES
3417 stop_share_mode_mgmt();
3418 #endif /* FAST_SHARE_MODES */
3420 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3421 exit(0);
3424 /****************************************************************************
3425 do some standard substitutions in a string
3426 ****************************************************************************/
3427 void standard_sub(int cnum,char *s)
3429 if (!strchr(s,'%')) return;
3431 if (VALID_CNUM(cnum))
3433 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3434 string_sub(s,"%P",Connections[cnum].connectpath);
3435 string_sub(s,"%u",Connections[cnum].user);
3436 if (strstr(s,"%H")) {
3437 char *home = get_home_dir(Connections[cnum].user);
3438 if (home) string_sub(s,"%H",home);
3440 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3442 standard_sub_basic(s);
3446 These flags determine some of the permissions required to do an operation
3448 Note that I don't set NEED_WRITE on some write operations because they
3449 are used by some brain-dead clients when printing, and I don't want to
3450 force write permissions on print services.
3452 #define AS_USER (1<<0)
3453 #define NEED_WRITE (1<<1)
3454 #define TIME_INIT (1<<2)
3455 #define CAN_IPC (1<<3)
3456 #define AS_GUEST (1<<5)
3460 define a list of possible SMB messages and their corresponding
3461 functions. Any message that has a NULL function is unimplemented -
3462 please feel free to contribute implementations!
3464 struct smb_message_struct
3466 int code;
3467 char *name;
3468 int (*fn)();
3469 int flags;
3470 #if PROFILING
3471 unsigned long time;
3472 #endif
3474 smb_messages[] = {
3476 /* CORE PROTOCOL */
3478 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3479 {SMBtcon,"SMBtcon",reply_tcon,0},
3480 {SMBtdis,"SMBtdis",reply_tdis,0},
3481 {SMBexit,"SMBexit",reply_exit,0},
3482 {SMBioctl,"SMBioctl",reply_ioctl,0},
3483 {SMBecho,"SMBecho",reply_echo,0},
3484 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3485 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3486 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3487 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3488 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3489 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3490 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3491 {SMBopen,"SMBopen",reply_open,AS_USER},
3493 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3494 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3495 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3497 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3498 {SMBread,"SMBread",reply_read,AS_USER},
3499 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3500 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3501 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3502 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3503 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3504 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3506 /* this is a Pathworks specific call, allowing the
3507 changing of the root path */
3508 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3510 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3511 {SMBflush,"SMBflush",reply_flush,AS_USER},
3512 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3513 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3514 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3515 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3516 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3517 {SMBlock,"SMBlock",reply_lock,AS_USER},
3518 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3520 /* CORE+ PROTOCOL FOLLOWS */
3522 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3523 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3524 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3525 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3526 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3528 /* LANMAN1.0 PROTOCOL FOLLOWS */
3530 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3531 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3532 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3533 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3534 {SMBwritec,"SMBwritec",NULL,AS_USER},
3535 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3536 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3537 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3538 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3539 {SMBioctls,"SMBioctls",NULL,AS_USER},
3540 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3541 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3543 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3544 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3545 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3546 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3548 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3549 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3550 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3552 /* LANMAN2.0 PROTOCOL FOLLOWS */
3553 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3554 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3555 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3556 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3558 /* messaging routines */
3559 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3560 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3561 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3562 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3564 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3566 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3567 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3568 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3569 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3572 /****************************************************************************
3573 return a string containing the function name of a SMB command
3574 ****************************************************************************/
3575 char *smb_fn_name(int type)
3577 static char *unknown_name = "SMBunknown";
3578 static int num_smb_messages =
3579 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3580 int match;
3582 for (match=0;match<num_smb_messages;match++)
3583 if (smb_messages[match].code == type)
3584 break;
3586 if (match == num_smb_messages)
3587 return(unknown_name);
3589 return(smb_messages[match].name);
3593 /****************************************************************************
3594 do a switch on the message type, and return the response size
3595 ****************************************************************************/
3596 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3598 static int pid= -1;
3599 int outsize = 0;
3600 static int num_smb_messages =
3601 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3602 int match;
3604 #if PROFILING
3605 struct timeval msg_start_time;
3606 struct timeval msg_end_time;
3607 static unsigned long total_time = 0;
3609 GetTimeOfDay(&msg_start_time);
3610 #endif
3612 if (pid == -1)
3613 pid = getpid();
3615 errno = 0;
3616 last_message = type;
3618 /* make sure this is an SMB packet */
3619 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3621 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3622 return(-1);
3625 for (match=0;match<num_smb_messages;match++)
3626 if (smb_messages[match].code == type)
3627 break;
3629 if (match == num_smb_messages)
3631 DEBUG(0,("Unknown message type %d!\n",type));
3632 outsize = reply_unknown(inbuf,outbuf);
3634 else
3636 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3637 if (smb_messages[match].fn)
3639 int cnum = SVAL(inbuf,smb_tid);
3640 int flags = smb_messages[match].flags;
3641 uint16 session_tag = SVAL(inbuf,smb_uid);
3643 /* does this protocol need to be run as root? */
3644 if (!(flags & AS_USER))
3645 unbecome_user();
3647 /* does this protocol need to be run as the connected user? */
3648 if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3649 if (flags & AS_GUEST)
3650 flags &= ~AS_USER;
3651 else
3652 return(ERROR(ERRSRV,ERRinvnid));
3654 /* this code is to work around a bug is MS client 3 without
3655 introducing a security hole - it needs to be able to do
3656 print queue checks as guest if it isn't logged in properly */
3657 if (flags & AS_USER)
3658 flags &= ~AS_GUEST;
3660 /* does it need write permission? */
3661 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3662 return(ERROR(ERRSRV,ERRaccess));
3664 /* ipc services are limited */
3665 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3666 return(ERROR(ERRSRV,ERRaccess));
3668 /* load service specific parameters */
3669 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3670 return(ERROR(ERRSRV,ERRaccess));
3672 /* does this protocol need to be run as guest? */
3673 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3674 return(ERROR(ERRSRV,ERRaccess));
3676 last_inbuf = inbuf;
3678 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3680 else
3682 outsize = reply_unknown(inbuf,outbuf);
3686 #if PROFILING
3687 GetTimeOfDay(&msg_end_time);
3688 if (!(smb_messages[match].flags & TIME_INIT))
3690 smb_messages[match].time = 0;
3691 smb_messages[match].flags |= TIME_INIT;
3694 unsigned long this_time =
3695 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3696 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3697 smb_messages[match].time += this_time;
3698 total_time += this_time;
3700 DEBUG(2,("TIME %s %d usecs %g pct\n",
3701 smb_fn_name(type),smb_messages[match].time,
3702 (100.0*smb_messages[match].time) / total_time));
3703 #endif
3705 return(outsize);
3709 /****************************************************************************
3710 construct a chained reply and add it to the already made reply
3711 **************************************************************************/
3712 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3714 static char *orig_inbuf;
3715 static char *orig_outbuf;
3716 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3717 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3718 char *inbuf2, *outbuf2;
3719 int outsize2;
3720 char inbuf_saved[smb_wct];
3721 char outbuf_saved[smb_wct];
3722 extern int chain_size;
3723 int wct = CVAL(outbuf,smb_wct);
3724 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3726 /* maybe its not chained */
3727 if (smb_com2 == 0xFF) {
3728 CVAL(outbuf,smb_vwv0) = 0xFF;
3729 return outsize;
3732 if (chain_size == 0) {
3733 /* this is the first part of the chain */
3734 orig_inbuf = inbuf;
3735 orig_outbuf = outbuf;
3738 /* we need to tell the client where the next part of the reply will be */
3739 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3740 CVAL(outbuf,smb_vwv0) = smb_com2;
3742 /* remember how much the caller added to the chain, only counting stuff
3743 after the parameter words */
3744 chain_size += outsize - smb_wct;
3746 /* work out pointers into the original packets. The
3747 headers on these need to be filled in */
3748 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3749 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3751 /* remember the original command type */
3752 smb_com1 = CVAL(orig_inbuf,smb_com);
3754 /* save the data which will be overwritten by the new headers */
3755 memcpy(inbuf_saved,inbuf2,smb_wct);
3756 memcpy(outbuf_saved,outbuf2,smb_wct);
3758 /* give the new packet the same header as the last part of the SMB */
3759 memmove(inbuf2,inbuf,smb_wct);
3761 /* create the in buffer */
3762 CVAL(inbuf2,smb_com) = smb_com2;
3764 /* create the out buffer */
3765 bzero(outbuf2,smb_size);
3766 set_message(outbuf2,0,0,True);
3767 CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3769 memcpy(outbuf2+4,inbuf2+4,4);
3770 CVAL(outbuf2,smb_rcls) = SUCCESS;
3771 CVAL(outbuf2,smb_reh) = 0;
3772 CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
3773 means a reply */
3774 SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3775 SSVAL(outbuf2,smb_err,SUCCESS);
3776 SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3777 SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3778 SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3779 SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3781 DEBUG(3,("Chained message\n"));
3782 show_msg(inbuf2);
3784 /* process the request */
3785 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3786 bufsize-chain_size);
3788 /* copy the new reply and request headers over the old ones, but
3789 preserve the smb_com field */
3790 memmove(orig_outbuf,outbuf2,smb_wct);
3791 CVAL(orig_outbuf,smb_com) = smb_com1;
3793 /* restore the saved data, being careful not to overwrite any
3794 data from the reply header */
3795 memcpy(inbuf2,inbuf_saved,smb_wct);
3797 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3798 if (ofs < 0) ofs = 0;
3799 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3802 return outsize2;
3807 /****************************************************************************
3808 construct a reply to the incoming packet
3809 ****************************************************************************/
3810 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3812 int type = CVAL(inbuf,smb_com);
3813 int outsize = 0;
3814 int msg_type = CVAL(inbuf,0);
3815 extern int chain_size;
3817 smb_last_time = time(NULL);
3819 chain_size = 0;
3820 chain_fnum = -1;
3822 bzero(outbuf,smb_size);
3824 if (msg_type != 0)
3825 return(reply_special(inbuf,outbuf));
3827 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3828 set_message(outbuf,0,0,True);
3830 memcpy(outbuf+4,inbuf+4,4);
3831 CVAL(outbuf,smb_rcls) = SUCCESS;
3832 CVAL(outbuf,smb_reh) = 0;
3833 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3834 means a reply */
3835 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3836 SSVAL(outbuf,smb_err,SUCCESS);
3837 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3838 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3839 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3840 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3842 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3844 outsize += chain_size;
3846 if(outsize > 4)
3847 smb_setlen(outbuf,outsize - 4);
3848 return(outsize);
3852 /****************************************************************************
3853 process commands from the client
3854 ****************************************************************************/
3855 static void process(void)
3857 static int trans_num = 0;
3858 int nread;
3859 extern int Client;
3861 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3862 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3863 if ((InBuffer == NULL) || (OutBuffer == NULL))
3864 return;
3866 InBuffer += SMB_ALIGNMENT;
3867 OutBuffer += SMB_ALIGNMENT;
3869 #if PRIME_NMBD
3870 DEBUG(3,("priming nmbd\n"));
3872 struct in_addr ip;
3873 ip = *interpret_addr2("localhost");
3874 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3875 *OutBuffer = 0;
3876 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3878 #endif
3880 while (True)
3882 int32 len;
3883 int msg_type;
3884 int msg_flags;
3885 int type;
3886 int deadtime = lp_deadtime()*60;
3887 int counter;
3888 int last_keepalive=0;
3889 int service_load_counter = 0;
3891 if (deadtime <= 0)
3892 deadtime = DEFAULT_SMBD_TIMEOUT;
3894 if (lp_readprediction())
3895 do_read_prediction();
3897 errno = 0;
3899 for (counter=SMBD_SELECT_LOOP;
3900 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3901 counter += SMBD_SELECT_LOOP)
3903 int i;
3904 time_t t;
3905 BOOL allidle = True;
3906 extern int keepalive;
3908 if (counter > 365 * 3600) /* big number of seconds. */
3910 counter = 0;
3911 service_load_counter = 0;
3914 if (smb_read_error == READ_EOF) {
3915 DEBUG(3,("end of file from client\n"));
3916 return;
3919 if (smb_read_error == READ_ERROR) {
3920 DEBUG(3,("receive_smb error (%s) exiting\n",
3921 strerror(errno)));
3922 return;
3925 t = time(NULL);
3927 /* become root again if waiting */
3928 unbecome_user();
3930 /* check for smb.conf reload */
3931 if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
3933 service_load_counter = counter;
3935 /* remove all unused services. reduce some of that memory overhead. */
3936 lp_killunused(snum_used);
3938 /* reload services, if files have changed. */
3939 reload_services(True);
3942 /* automatic timeout if all connections are closed */
3943 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3944 DEBUG(2,("%s Closing idle connection\n",timestring()));
3945 return;
3948 if (keepalive && (counter-last_keepalive)>keepalive) {
3949 extern int password_client;
3950 if (!send_keepalive(Client)) {
3951 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3952 return;
3954 /* also send a keepalive to the password server if its still
3955 connected */
3956 if (password_client != -1)
3957 send_keepalive(password_client);
3958 last_keepalive = counter;
3961 /* check for connection timeouts */
3962 for (i=0;i<MAX_CONNECTIONS;i++)
3963 if (Connections[i].open)
3965 /* close dirptrs on connections that are idle */
3966 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3967 dptr_idlecnum(i);
3969 if (Connections[i].num_files_open > 0 ||
3970 (t-Connections[i].lastused)<deadtime)
3971 allidle = False;
3974 if (allidle && num_connections_open>0) {
3975 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3976 return;
3980 msg_type = CVAL(InBuffer,0);
3981 msg_flags = CVAL(InBuffer,1);
3982 type = CVAL(InBuffer,smb_com);
3984 len = smb_len(InBuffer);
3986 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3988 nread = len + 4;
3990 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3992 #ifdef WITH_VTP
3993 if(trans_num == 1 && VT_Check(InBuffer)) {
3994 VT_Process();
3995 return;
3997 #endif
4000 if (msg_type == 0)
4001 show_msg(InBuffer);
4003 nread = construct_reply(InBuffer,OutBuffer,nread,max_send);
4005 if(nread > 0) {
4006 if (CVAL(OutBuffer,0) == 0)
4007 show_msg(OutBuffer);
4009 if (nread != smb_len(OutBuffer) + 4)
4011 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
4012 nread,
4013 smb_len(OutBuffer)));
4015 else
4016 send_smb(Client,OutBuffer);
4018 trans_num++;
4023 /****************************************************************************
4024 initialise connect, service and file structs
4025 ****************************************************************************/
4026 static void init_structs(void )
4028 int i;
4029 get_myname(myhostname,NULL);
4031 for (i=0;i<MAX_CONNECTIONS;i++)
4033 Connections[i].open = False;
4034 Connections[i].num_files_open=0;
4035 Connections[i].lastused=0;
4036 Connections[i].used=False;
4037 string_init(&Connections[i].user,"");
4038 string_init(&Connections[i].dirpath,"");
4039 string_init(&Connections[i].connectpath,"");
4040 string_init(&Connections[i].origpath,"");
4043 for (i=0;i<MAX_OPEN_FILES;i++)
4045 Files[i].open = False;
4046 string_init(&Files[i].name,"");
4050 for (i=0;i<MAX_OPEN_FILES;i++)
4052 file_fd_struct *fd_ptr = &FileFd[i];
4053 fd_ptr->ref_count = 0;
4054 fd_ptr->dev = (int32)-1;
4055 fd_ptr->inode = (int32)-1;
4056 fd_ptr->fd = -1;
4057 fd_ptr->fd_readonly = -1;
4058 fd_ptr->fd_writeonly = -1;
4059 fd_ptr->real_open_flags = -1;
4062 init_dptrs();
4065 /****************************************************************************
4066 usage on the program
4067 ****************************************************************************/
4068 static void usage(char *pname)
4070 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4072 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
4073 printf("Version %s\n",VERSION);
4074 printf("\t-D become a daemon\n");
4075 printf("\t-p port listen on the specified port\n");
4076 printf("\t-d debuglevel set the debuglevel\n");
4077 printf("\t-l log basename. Basename for log/debug files\n");
4078 printf("\t-s services file. Filename of services file\n");
4079 printf("\t-P passive only\n");
4080 printf("\t-a overwrite log file, don't append\n");
4081 printf("\n");
4085 /****************************************************************************
4086 main program
4087 ****************************************************************************/
4088 int main(int argc,char *argv[])
4090 extern BOOL append_log;
4091 /* shall I run as a daemon */
4092 BOOL is_daemon = False;
4093 int port = SMB_PORT;
4094 int opt;
4095 extern char *optarg;
4096 char pidFile[100] = { 0 };
4098 #ifdef NEED_AUTH_PARAMETERS
4099 set_auth_parameters(argc,argv);
4100 #endif
4102 #ifdef SecureWare
4103 setluid(0);
4104 #endif
4106 append_log = True;
4108 TimeInit();
4110 strcpy(debugf,SMBLOGFILE);
4112 setup_logging(argv[0],False);
4114 charset_initialise(-1);
4116 /* make absolutely sure we run as root - to handle cases whre people
4117 are crazy enough to have it setuid */
4118 #ifdef USE_SETRES
4119 setresuid(0,0,0);
4120 #else
4121 setuid(0);
4122 seteuid(0);
4123 setuid(0);
4124 seteuid(0);
4125 #endif
4127 fault_setup(exit_server);
4128 signal(SIGTERM , SIGNAL_CAST dflt_sig);
4130 /* we want total control over the permissions on created files,
4131 so set our umask to 0 */
4132 umask(0);
4134 GetWd(OriginalDir);
4136 init_uid();
4138 /* this is for people who can't start the program correctly */
4139 while (argc > 1 && (*argv[1] != '-'))
4141 argv++;
4142 argc--;
4145 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
4146 switch (opt)
4148 case 'f':
4149 strncpy(pidFile, optarg, sizeof(pidFile));
4150 break;
4151 case 'O':
4152 strcpy(user_socket_options,optarg);
4153 break;
4154 case 'i':
4155 strcpy(scope,optarg);
4156 break;
4157 case 'P':
4159 extern BOOL passive;
4160 passive = True;
4162 break;
4163 case 's':
4164 strcpy(servicesf,optarg);
4165 break;
4166 case 'l':
4167 strcpy(debugf,optarg);
4168 break;
4169 case 'a':
4171 extern BOOL append_log;
4172 append_log = !append_log;
4174 break;
4175 case 'D':
4176 is_daemon = True;
4177 break;
4178 case 'd':
4179 if (*optarg == 'A')
4180 DEBUGLEVEL = 10000;
4181 else
4182 DEBUGLEVEL = atoi(optarg);
4183 break;
4184 case 'p':
4185 port = atoi(optarg);
4186 break;
4187 case 'h':
4188 usage(argv[0]);
4189 exit(0);
4190 break;
4191 default:
4192 usage(argv[0]);
4193 exit(1);
4196 reopen_logs();
4198 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4199 DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n"));
4201 #ifndef NO_GETRLIMIT
4202 #ifdef RLIMIT_NOFILE
4204 struct rlimit rlp;
4205 getrlimit(RLIMIT_NOFILE, &rlp);
4206 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4207 setrlimit(RLIMIT_NOFILE, &rlp);
4208 getrlimit(RLIMIT_NOFILE, &rlp);
4209 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4211 #endif
4212 #endif
4215 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4216 getuid(),getgid(),geteuid(),getegid()));
4218 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4220 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4221 exit(1);
4224 init_structs();
4226 if (!reload_services(False))
4227 return(-1);
4229 charset_initialise(lp_client_code_page());
4231 strcpy(myworkgroup, lp_workgroup());
4233 #ifndef NO_SIGNAL_TEST
4234 signal(SIGHUP,SIGNAL_CAST sig_hup);
4235 #endif
4237 DEBUG(3,("%s loaded services\n",timestring()));
4239 if (!is_daemon && !is_a_socket(0))
4241 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4242 is_daemon = True;
4245 if (is_daemon)
4247 DEBUG(3,("%s becoming a daemon\n",timestring()));
4248 become_daemon();
4251 if (*pidFile)
4253 int fd;
4254 char buf[20];
4256 if ((fd = open(pidFile,
4257 O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4259 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4260 exit(1);
4262 if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4264 DEBUG(0,("ERROR: smbd is already running\n"));
4265 exit(1);
4267 sprintf(buf, "%u\n", (unsigned int) getpid());
4268 if (write(fd, buf, strlen(buf)) < 0)
4270 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4271 exit(1);
4273 /* Leave pid file open & locked for the duration... */
4276 if (!open_sockets(is_daemon,port))
4277 exit(1);
4279 #ifdef FAST_SHARE_MODES
4280 if (!start_share_mode_mgmt())
4281 exit(1);
4282 #endif /* FAST_SHARE_MODES */
4284 /* possibly reload the services file. */
4285 reload_services(True);
4287 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
4289 if (*lp_rootdir())
4291 if (sys_chroot(lp_rootdir()) == 0)
4292 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4295 process();
4296 close_sockets();
4298 exit_server("normal exit");
4299 return(0);