loadparm.c: Added "force create mode" and "force directory mode" params.
[Samba/gbeck.git] / source / smbd / server.c
blob203bdb8da89850adc7df8eb91b0f29b6a6648b1c
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 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
183 if (!((sbuf->st_mode & S_IWOTH) ||
184 Connections[cnum].admin_user ||
185 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
186 ((sbuf->st_mode & S_IWGRP) &&
187 in_group(sbuf->st_gid,current_user.gid,
188 current_user.ngroups,current_user.igroups))))
189 result |= aRONLY;
190 } else {
191 if ((sbuf->st_mode & S_IWUSR) == 0)
192 result |= aRONLY;
195 if ((sbuf->st_mode & S_IXUSR) != 0)
196 result |= aARCH;
198 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
199 result |= aSYSTEM;
201 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
202 result |= aHIDDEN;
204 if (S_ISDIR(sbuf->st_mode))
205 result = aDIR | (result & aRONLY);
207 #if LINKS_READ_ONLY
208 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
209 result |= aRONLY;
210 #endif
212 /* hide files with a name starting with a . */
213 if (lp_hide_dot_files(SNUM(cnum)))
215 char *p = strrchr(path,'/');
216 if (p)
217 p++;
218 else
219 p = path;
221 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
222 result |= aHIDDEN;
225 return(result);
229 /*******************************************************************
230 chmod a file - but preserve some bits
231 ********************************************************************/
232 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
234 struct stat st1;
235 int mask=0;
236 int tmp;
237 int unixmode;
239 if (!st) {
240 st = &st1;
241 if (sys_stat(fname,st)) return(-1);
244 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
246 if (dos_mode(cnum,fname,st) == dosmode) return(0);
248 unixmode = unix_mode(cnum,dosmode);
250 /* preserve the s bits */
251 mask |= (S_ISUID | S_ISGID);
253 /* preserve the t bit */
254 #ifdef S_ISVTX
255 mask |= S_ISVTX;
256 #endif
258 /* possibly preserve the x bits */
259 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
260 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
261 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
263 unixmode |= (st->st_mode & mask);
265 /* if we previously had any r bits set then leave them alone */
266 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
267 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
268 unixmode |= tmp;
271 /* if we previously had any w bits set then leave them alone
272 if the new mode is not rdonly */
273 if (!IS_DOS_READONLY(dosmode) &&
274 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
275 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
276 unixmode |= tmp;
279 return(sys_chmod(fname,unixmode));
283 /****************************************************************************
284 check if two filenames are equal
286 this needs to be careful about whether we are case sensitive
287 ****************************************************************************/
288 static BOOL fname_equal(char *name1, char *name2)
290 int l1 = strlen(name1);
291 int l2 = strlen(name2);
293 /* handle filenames ending in a single dot */
294 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
296 BOOL ret;
297 name1[l1-1] = 0;
298 ret = fname_equal(name1,name2);
299 name1[l1-1] = '.';
300 return(ret);
303 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
305 BOOL ret;
306 name2[l2-1] = 0;
307 ret = fname_equal(name1,name2);
308 name2[l2-1] = '.';
309 return(ret);
312 /* now normal filename handling */
313 if (case_sensitive)
314 return(strcmp(name1,name2) == 0);
316 return(strequal(name1,name2));
320 /****************************************************************************
321 mangle the 2nd name and check if it is then equal to the first name
322 ****************************************************************************/
323 static BOOL mangled_equal(char *name1, char *name2)
325 pstring tmpname;
327 if (is_8_3(name2, True))
328 return(False);
330 strcpy(tmpname,name2);
331 mangle_name_83(tmpname);
333 return(strequal(name1,tmpname));
337 /****************************************************************************
338 scan a directory to find a filename, matching without case sensitivity
340 If the name looks like a mangled name then try via the mangling functions
341 ****************************************************************************/
342 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
344 void *cur_dir;
345 char *dname;
346 BOOL mangled;
347 pstring name2;
349 mangled = is_mangled(name);
351 /* handle null paths */
352 if (*path == 0)
353 path = ".";
355 if (docache && (dname = DirCacheCheck(path,name,snum))) {
356 strcpy(name, dname);
357 return(True);
360 if (mangled)
361 check_mangled_stack(name);
363 /* open the directory */
364 if (!(cur_dir = OpenDir(path)))
366 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
367 return(False);
370 /* now scan for matching names */
371 while ((dname = ReadDirName(cur_dir)))
373 if (*dname == '.' &&
374 (strequal(dname,".") || strequal(dname,"..")))
375 continue;
377 strcpy(name2,dname);
378 if (!name_map_mangle(name2,False,snum)) continue;
380 if ((mangled && mangled_equal(name,name2))
381 || fname_equal(name, name2))
383 /* we've found the file, change it's name and return */
384 if (docache) DirCacheAdd(path,name,dname,snum);
385 strcpy(name, dname);
386 CloseDir(cur_dir);
387 return(True);
391 CloseDir(cur_dir);
392 return(False);
395 /****************************************************************************
396 This routine is called to convert names from the dos namespace to unix
397 namespace. It needs to handle any case conversions, mangling, format
398 changes etc.
400 We assume that we have already done a chdir() to the right "root" directory
401 for this service.
403 The function will return False if some part of the name except for the last
404 part cannot be resolved
406 If the saved_last_component != 0, then the unmodified last component
407 of the pathname is returned there. This is used in an exceptional
408 case in reply_mv (so far). If saved_last_component == 0 then nothing
409 is returned there.
410 ****************************************************************************/
411 BOOL unix_convert(char *name,int cnum,pstring saved_last_component)
413 struct stat st;
414 char *start, *end;
415 pstring dirpath;
417 *dirpath = 0;
418 if(saved_last_component)
419 *saved_last_component = 0;
421 /* convert to basic unix format - removing \ chars and cleaning it up */
422 unix_format(name);
423 unix_clean_name(name);
425 /* names must be relative to the root of the service - trim any leading /.
426 also trim trailing /'s */
427 trim_string(name,"/","/");
430 * Ensure saved_last_component is valid even if file exists.
432 if(saved_last_component) {
433 end = strrchr(name, '/');
434 if(end)
435 strcpy(saved_last_component, end + 1);
436 else
437 strcpy(saved_last_component, name);
440 if (!case_sensitive &&
441 (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
442 strnorm(name);
444 /* check if it's a printer file */
445 if (Connections[cnum].printer)
447 if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
449 char *s;
450 fstring name2;
451 sprintf(name2,"%.6s.XXXXXX",remote_machine);
452 /* sanitise the name */
453 for (s=name2 ; *s ; s++)
454 if (!issafe(*s)) *s = '_';
455 strcpy(name,(char *)mktemp(name2));
457 return(True);
460 /* stat the name - if it exists then we are all done! */
461 if (sys_stat(name,&st) == 0)
462 return(True);
464 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
466 /* a special case - if we don't have any mangling chars and are case
467 sensitive then searching won't help */
468 if (case_sensitive && !is_mangled(name) &&
469 !lp_strip_dot() && !use_mangled_map)
470 return(False);
472 /* now we need to recursively match the name against the real
473 directory structure */
475 start = name;
476 while (strncmp(start,"./",2) == 0)
477 start += 2;
479 /* now match each part of the path name separately, trying the names
480 as is first, then trying to scan the directory for matching names */
481 for (;start;start = (end?end+1:(char *)NULL))
483 /* pinpoint the end of this section of the filename */
484 end = strchr(start, '/');
486 /* chop the name at this point */
487 if (end) *end = 0;
489 if(saved_last_component != 0)
490 strcpy(saved_last_component, end ? end + 1 : start);
492 /* check if the name exists up to this point */
493 if (sys_stat(name, &st) == 0)
495 /* it exists. it must either be a directory or this must be
496 the last part of the path for it to be OK */
497 if (end && !(st.st_mode & S_IFDIR))
499 /* an intermediate part of the name isn't a directory */
500 DEBUG(5,("Not a dir %s\n",start));
501 *end = '/';
502 return(False);
505 else
507 pstring rest;
509 *rest = 0;
511 /* remember the rest of the pathname so it can be restored
512 later */
513 if (end) strcpy(rest,end+1);
515 /* try to find this part of the path in the directory */
516 if (strchr(start,'?') || strchr(start,'*') ||
517 !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
519 if (end)
521 /* an intermediate part of the name can't be found */
522 DEBUG(5,("Intermediate not found %s\n",start));
523 *end = '/';
524 return(False);
527 /* just the last part of the name doesn't exist */
528 /* we may need to strupper() or strlower() it in case
529 this conversion is being used for file creation
530 purposes */
531 /* if the filename is of mixed case then don't normalise it */
532 if (!case_preserve &&
533 (!strhasupper(start) || !strhaslower(start)))
534 strnorm(start);
536 /* check on the mangled stack to see if we can recover the
537 base of the filename */
538 if (is_mangled(start))
539 check_mangled_stack(start);
541 DEBUG(5,("New file %s\n",start));
542 return(True);
545 /* restore the rest of the string */
546 if (end)
548 strcpy(start+strlen(start)+1,rest);
549 end = start + strlen(start);
553 /* add to the dirpath that we have resolved so far */
554 if (*dirpath) strcat(dirpath,"/");
555 strcat(dirpath,start);
557 /* restore the / that we wiped out earlier */
558 if (end) *end = '/';
561 /* the name has been resolved */
562 DEBUG(5,("conversion finished %s\n",name));
563 return(True);
567 /****************************************************************************
568 normalise for DOS usage
569 ****************************************************************************/
570 static void disk_norm(int *bsize,int *dfree,int *dsize)
572 /* check if the disk is beyond the max disk size */
573 int maxdisksize = lp_maxdisksize();
574 if (maxdisksize) {
575 /* convert to blocks - and don't overflow */
576 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
577 if (*dsize > maxdisksize) *dsize = maxdisksize;
578 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
579 applications getting
580 div by 0 errors */
583 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
585 *dfree /= 2;
586 *dsize /= 2;
587 *bsize *= 2;
588 if (*bsize > WORDMAX )
590 *bsize = WORDMAX;
591 if (*dsize > WORDMAX)
592 *dsize = WORDMAX;
593 if (*dfree > WORDMAX)
594 *dfree = WORDMAX;
595 break;
600 /****************************************************************************
601 return number of 1K blocks available on a path and total number
602 ****************************************************************************/
603 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
605 char *df_command = lp_dfree_command();
606 #ifndef NO_STATFS
607 #ifdef USE_STATVFS
608 struct statvfs fs;
609 #else
610 #ifdef ULTRIX
611 struct fs_data fs;
612 #else
613 struct statfs fs;
614 #endif
615 #endif
616 #endif
618 #ifdef QUOTAS
619 if (disk_quotas(path, bsize, dfree, dsize))
621 disk_norm(bsize,dfree,dsize);
622 return(((*bsize)/1024)*(*dfree));
624 #endif
627 /* possibly use system() to get the result */
628 if (df_command && *df_command)
630 int ret;
631 pstring syscmd;
632 pstring outfile;
634 sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
635 sprintf(syscmd,"%s %s",df_command,path);
636 standard_sub_basic(syscmd);
638 ret = smbrun(syscmd,outfile,False);
639 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
642 FILE *f = fopen(outfile,"r");
643 *dsize = 0;
644 *dfree = 0;
645 *bsize = 1024;
646 if (f)
648 fscanf(f,"%d %d %d",dsize,dfree,bsize);
649 fclose(f);
651 else
652 DEBUG(0,("Can't open %s\n",outfile));
655 unlink(outfile);
656 disk_norm(bsize,dfree,dsize);
657 return(((*bsize)/1024)*(*dfree));
660 #ifdef NO_STATFS
661 DEBUG(1,("Warning - no statfs function\n"));
662 return(1);
663 #else
664 #ifdef STATFS4
665 if (statfs(path,&fs,sizeof(fs),0) != 0)
666 #else
667 #ifdef USE_STATVFS
668 if (statvfs(path, &fs))
669 #else
670 #ifdef STATFS3
671 if (statfs(path,&fs,sizeof(fs)) == -1)
672 #else
673 if (statfs(path,&fs) == -1)
674 #endif /* STATFS3 */
675 #endif /* USE_STATVFS */
676 #endif /* STATFS4 */
678 DEBUG(3,("dfree call failed code errno=%d\n",errno));
679 *bsize = 1024;
680 *dfree = 1;
681 *dsize = 1;
682 return(((*bsize)/1024)*(*dfree));
685 #ifdef ULTRIX
686 *bsize = 1024;
687 *dfree = fs.fd_req.bfree;
688 *dsize = fs.fd_req.btot;
689 #else
690 #ifdef USE_STATVFS
691 *bsize = fs.f_frsize;
692 #else
693 #ifdef USE_F_FSIZE
694 /* eg: osf1 has f_fsize = fundamental filesystem block size,
695 f_bsize = optimal transfer block size (MX: 94-04-19) */
696 *bsize = fs.f_fsize;
697 #else
698 *bsize = fs.f_bsize;
699 #endif /* STATFS3 */
700 #endif /* USE_STATVFS */
702 #ifdef STATFS4
703 *dfree = fs.f_bfree;
704 #else
705 *dfree = fs.f_bavail;
706 #endif /* STATFS4 */
707 *dsize = fs.f_blocks;
708 #endif /* ULTRIX */
710 #if defined(SCO) || defined(ISC) || defined(MIPS)
711 *bsize = 512;
712 #endif
714 /* handle rediculous bsize values - some OSes are broken */
715 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
717 disk_norm(bsize,dfree,dsize);
719 if (*bsize < 256)
720 *bsize = 512;
721 if ((*dsize)<1)
723 DEBUG(0,("dfree seems to be broken on your system\n"));
724 *dsize = 20*1024*1024/(*bsize);
725 *dfree = MAX(1,*dfree);
727 return(((*bsize)/1024)*(*dfree));
728 #endif
732 /****************************************************************************
733 wrap it to get filenames right
734 ****************************************************************************/
735 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
737 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
742 /****************************************************************************
743 check a filename - possibly caling reducename
745 This is called by every routine before it allows an operation on a filename.
746 It does any final confirmation necessary to ensure that the filename is
747 a valid one for the user to access.
748 ****************************************************************************/
749 BOOL check_name(char *name,int cnum)
751 BOOL ret;
753 errno = 0;
755 if( is_vetoed_path(name))
757 DEBUG(5,("file path name %s vetoed\n",name));
758 return(0);
761 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
762 if (!ret)
763 DEBUG(5,("check_name on %s failed\n",name));
765 return(ret);
768 /****************************************************************************
769 check a filename - possibly caling reducename
770 ****************************************************************************/
771 static void check_for_pipe(char *fname)
773 /* special case of pipe opens */
774 char s[10];
775 StrnCpy(s,fname,9);
776 strlower(s);
777 if (strstr(s,"pipe/"))
779 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
780 unix_ERR_class = ERRSRV;
781 unix_ERR_code = ERRaccess;
785 /****************************************************************************
786 fd support routines - attempt to do a sys_open
787 ****************************************************************************/
789 int fd_attempt_open(char *fname, int flags, int mode)
791 int fd = sys_open(fname,flags,mode);
793 /* Fix for files ending in '.' */
794 if((fd == -1) && (errno == ENOENT) &&
795 (strchr(fname,'.')==NULL))
797 strcat(fname,".");
798 fd = sys_open(fname,flags,mode);
801 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
802 if ((fd == -1) && (errno == ENAMETOOLONG))
804 int max_len;
805 char *p = strrchr(fname, '/');
807 if (p == fname) /* name is "/xxx" */
809 max_len = pathconf("/", _PC_NAME_MAX);
810 p++;
812 else if ((p == NULL) || (p == fname))
814 p = fname;
815 max_len = pathconf(".", _PC_NAME_MAX);
817 else
819 *p = '\0';
820 max_len = pathconf(fname, _PC_NAME_MAX);
821 *p = '/';
822 p++;
824 if (strlen(p) > max_len)
826 char tmp = p[max_len];
828 p[max_len] = '\0';
829 if ((fd = sys_open(fname,flags,mode)) == -1)
830 p[max_len] = tmp;
833 #endif
834 return fd;
837 /****************************************************************************
838 fd support routines - attempt to find an already open file by dev
839 and inode - increments the ref_count of the returned file_fd_struct *.
840 ****************************************************************************/
841 file_fd_struct *fd_get_already_open(struct stat *sbuf)
843 int i;
844 file_fd_struct *fd_ptr;
846 if(sbuf == 0)
847 return 0;
849 for(i = 0; i <= max_file_fd_used; i++) {
850 fd_ptr = &FileFd[i];
851 if((fd_ptr->ref_count > 0) &&
852 (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
853 (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
854 fd_ptr->ref_count++;
855 DEBUG(3,
856 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
857 i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
858 return fd_ptr;
861 return 0;
864 /****************************************************************************
865 fd support routines - attempt to find a empty slot in the FileFd array.
866 Increments the ref_count of the returned entry.
867 ****************************************************************************/
868 file_fd_struct *fd_get_new()
870 int i;
871 file_fd_struct *fd_ptr;
873 for(i = 0; i < MAX_OPEN_FILES; i++) {
874 fd_ptr = &FileFd[i];
875 if(fd_ptr->ref_count == 0) {
876 fd_ptr->dev = (uint32)-1;
877 fd_ptr->inode = (uint32)-1;
878 fd_ptr->fd = -1;
879 fd_ptr->fd_readonly = -1;
880 fd_ptr->fd_writeonly = -1;
881 fd_ptr->real_open_flags = -1;
882 fd_ptr->ref_count++;
883 /* Increment max used counter if neccessary, cuts down
884 on search time when re-using */
885 if(i > max_file_fd_used)
886 max_file_fd_used = i;
887 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
888 i, fd_ptr->dev, fd_ptr->inode));
889 return fd_ptr;
892 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
893 n"));
894 return 0;
897 /****************************************************************************
898 fd support routines - attempt to re-open an already open fd as O_RDWR.
899 Save the already open fd (we cannot close due to POSIX file locking braindamage.
900 ****************************************************************************/
902 void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
904 int fd = sys_open( fname, O_RDWR, mode);
906 if(fd == -1)
907 return;
909 if(fd_ptr->real_open_flags == O_RDONLY)
910 fd_ptr->fd_readonly = fd_ptr->fd;
911 if(fd_ptr->real_open_flags == O_WRONLY)
912 fd_ptr->fd_writeonly = fd_ptr->fd;
914 fd_ptr->fd = fd;
915 fd_ptr->real_open_flags = O_RDWR;
918 /****************************************************************************
919 fd support routines - attempt to close the file referenced by this fd.
920 Decrements the ref_count and returns it.
921 ****************************************************************************/
922 int fd_attempt_close(file_fd_struct *fd_ptr)
924 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
925 fd_ptr - &FileFd[0],
926 fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
927 fd_ptr->real_open_flags,
928 fd_ptr->ref_count));
929 if(fd_ptr->ref_count > 0) {
930 fd_ptr->ref_count--;
931 if(fd_ptr->ref_count == 0) {
932 if(fd_ptr->fd != -1)
933 close(fd_ptr->fd);
934 if(fd_ptr->fd_readonly != -1)
935 close(fd_ptr->fd_readonly);
936 if(fd_ptr->fd_writeonly != -1)
937 close(fd_ptr->fd_writeonly);
938 fd_ptr->fd = -1;
939 fd_ptr->fd_readonly = -1;
940 fd_ptr->fd_writeonly = -1;
941 fd_ptr->real_open_flags = -1;
942 fd_ptr->dev = (uint32)-1;
943 fd_ptr->inode = (uint32)-1;
946 return fd_ptr->ref_count;
949 /****************************************************************************
950 open a file
951 ****************************************************************************/
952 static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
954 extern struct current_user current_user;
955 pstring fname;
956 struct stat statbuf;
957 file_fd_struct *fd_ptr;
959 Files[fnum].open = False;
960 Files[fnum].fd_ptr = 0;
961 errno = EPERM;
963 strcpy(fname,fname1);
965 /* check permissions */
966 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
968 DEBUG(3,("Permission denied opening %s\n",fname));
969 check_for_pipe(fname);
970 return;
973 /* this handles a bug in Win95 - it doesn't say to create the file when it
974 should */
975 if (Connections[cnum].printer)
976 flags |= O_CREAT;
979 if (flags == O_WRONLY)
980 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
983 #if UTIME_WORKAROUND
984 /* XXXX - is this OK?? */
985 /* this works around a utime bug but can cause other problems */
986 if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
987 sys_unlink(fname);
988 #endif
991 * Ensure we have a valid struct stat so we can search the
992 * open fd table.
994 if(sbuf == 0) {
995 if(stat(fname, &statbuf) < 0) {
996 if(errno != ENOENT) {
997 DEBUG(3,("Error doing stat on file %s (%s)\n",
998 fname,strerror(errno)));
1000 check_for_pipe(fname);
1001 return;
1003 sbuf = 0;
1004 } else {
1005 sbuf = &statbuf;
1010 * Check to see if we have this file already
1011 * open. If we do, just use the already open fd and increment the
1012 * reference count (fd_get_already_open increments the ref_count).
1014 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
1016 int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
1018 /* File was already open. */
1019 if((flags & O_CREAT) && (flags & O_EXCL)) {
1020 fd_ptr->ref_count--;
1021 errno = EEXIST;
1022 return;
1026 * If not opened O_RDWR try
1027 * and do that here - a chmod may have been done
1028 * between the last open and now.
1030 if(fd_ptr->real_open_flags != O_RDWR)
1031 fd_attempt_reopen(fname, mode, fd_ptr);
1034 * Ensure that if we wanted write access
1035 * it has been opened for write, and if we wanted read it
1036 * was open for read.
1038 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1039 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1040 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1041 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1042 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1043 check_for_pipe(fname);
1044 fd_ptr->ref_count--;
1045 return;
1048 } else {
1049 int open_flags;
1050 /* We need to allocate a new file_fd_struct (this increments the
1051 ref_count). */
1052 if((fd_ptr = fd_get_new()) == 0)
1053 return;
1055 * Whatever the requested flags, attempt read/write access,
1056 * as we don't know what flags future file opens may require.
1057 * If this fails, try again with the required flags.
1058 * Even if we open read/write when only read access was
1059 * requested the setting of the can_write flag in
1060 * the file_struct will protect us from errant
1061 * write requests. We never need to worry about O_APPEND
1062 * as this is not set anywhere in Samba.
1064 fd_ptr->real_open_flags = O_RDWR;
1065 /* Set the flags as needed without the read/write modes. */
1066 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1067 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1069 * On some systems opening a file for R/W access on a read only
1070 * filesystems sets errno to EROFS.
1072 #ifdef EROFS
1073 if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1074 #else /* No EROFS */
1075 if((fd_ptr->fd == -1) && (errno == EACCES)) {
1076 #endif /* EROFS */
1077 if(flags & O_WRONLY) {
1078 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1079 fd_ptr->real_open_flags = O_WRONLY;
1080 } else {
1081 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1082 fd_ptr->real_open_flags = O_RDONLY;
1087 if ((fd_ptr->fd >=0) &&
1088 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1089 pstring dname;
1090 int dum1,dum2,dum3;
1091 char *p;
1092 strcpy(dname,fname);
1093 p = strrchr(dname,'/');
1094 if (p) *p = 0;
1095 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1096 lp_minprintspace(SNUM(cnum))) {
1097 fd_attempt_close(fd_ptr);
1098 Files[fnum].fd_ptr = 0;
1099 if(fd_ptr->ref_count == 0)
1100 sys_unlink(fname);
1101 errno = ENOSPC;
1102 return;
1106 if (fd_ptr->fd < 0)
1108 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1109 fname,strerror(errno),flags));
1110 /* Ensure the ref_count is decremented. */
1111 fd_attempt_close(fd_ptr);
1112 check_for_pipe(fname);
1113 return;
1116 if (fd_ptr->fd >= 0)
1118 if(sbuf == 0) {
1119 /* Do the fstat */
1120 if(fstat(fd_ptr->fd, &statbuf) == -1) {
1121 /* Error - backout !! */
1122 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1123 fd_ptr->fd, fname,strerror(errno)));
1124 /* Ensure the ref_count is decremented. */
1125 fd_attempt_close(fd_ptr);
1126 return;
1128 sbuf = &statbuf;
1130 /* Set the correct entries in fd_ptr. */
1131 fd_ptr->dev = (uint32)sbuf->st_dev;
1132 fd_ptr->inode = (uint32)sbuf->st_ino;
1134 Files[fnum].fd_ptr = fd_ptr;
1135 Connections[cnum].num_files_open++;
1136 Files[fnum].mode = sbuf->st_mode;
1137 GetTimeOfDay(&Files[fnum].open_time);
1138 Files[fnum].uid = current_user.id;
1139 Files[fnum].size = 0;
1140 Files[fnum].pos = -1;
1141 Files[fnum].open = True;
1142 Files[fnum].mmap_ptr = NULL;
1143 Files[fnum].mmap_size = 0;
1144 Files[fnum].can_lock = True;
1145 Files[fnum].can_read = ((flags & O_WRONLY)==0);
1146 Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1147 Files[fnum].share_mode = 0;
1148 Files[fnum].print_file = Connections[cnum].printer;
1149 Files[fnum].modified = False;
1150 Files[fnum].cnum = cnum;
1151 string_set(&Files[fnum].name,dos_to_unix(fname,False));
1152 Files[fnum].wbmpx_ptr = NULL;
1155 * If the printer is marked as postscript output a leading
1156 * file identifier to ensure the file is treated as a raw
1157 * postscript file.
1158 * This has a similar effect as CtrlD=0 in WIN.INI file.
1159 * tim@fsg.com 09/06/94
1161 if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
1162 Files[fnum].can_write)
1164 DEBUG(3,("Writing postscript line\n"));
1165 write_file(fnum,"%!\n",3);
1168 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1169 timestring(),Connections[cnum].user,fname,
1170 BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1171 Connections[cnum].num_files_open,fnum));
1175 #if USE_MMAP
1176 /* mmap it if read-only */
1177 if (!Files[fnum].can_write)
1179 Files[fnum].mmap_size = file_size(fname);
1180 Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1181 PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
1183 if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1185 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1186 Files[fnum].mmap_ptr = NULL;
1189 #endif
1192 /*******************************************************************
1193 sync a file
1194 ********************************************************************/
1195 void sync_file(int fnum)
1197 #ifndef NO_FSYNC
1198 fsync(Files[fnum].fd_ptr->fd);
1199 #endif
1202 /****************************************************************************
1203 run a file if it is a magic script
1204 ****************************************************************************/
1205 static void check_magic(int fnum,int cnum)
1207 if (!*lp_magicscript(SNUM(cnum)))
1208 return;
1210 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1213 char *p;
1214 if (!(p = strrchr(Files[fnum].name,'/')))
1215 p = Files[fnum].name;
1216 else
1217 p++;
1219 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1220 return;
1224 int ret;
1225 pstring magic_output;
1226 pstring fname;
1227 strcpy(fname,Files[fnum].name);
1229 if (*lp_magicoutput(SNUM(cnum)))
1230 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1231 else
1232 sprintf(magic_output,"%s.out",fname);
1234 chmod(fname,0755);
1235 ret = smbrun(fname,magic_output,False);
1236 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1237 unlink(fname);
1242 /****************************************************************************
1243 close a file - possibly invalidating the read prediction
1244 ****************************************************************************/
1245 void close_file(int fnum)
1247 files_struct *fs_p = &Files[fnum];
1248 int cnum = fs_p->cnum;
1249 uint32 dev = fs_p->fd_ptr->dev;
1250 uint32 inode = fs_p->fd_ptr->inode;
1251 share_lock_token token;
1253 invalidate_read_prediction(fs_p->fd_ptr->fd);
1254 fs_p->open = False;
1255 Connections[cnum].num_files_open--;
1256 if(fs_p->wbmpx_ptr)
1258 free((char *)fs_p->wbmpx_ptr);
1259 fs_p->wbmpx_ptr = NULL;
1262 #if USE_MMAP
1263 if(fs_p->mmap_ptr)
1265 munmap(fs_p->mmap_ptr,fs_p->mmap_size);
1266 fs_p->mmap_ptr = NULL;
1268 #endif
1270 if (lp_share_modes(SNUM(cnum)))
1272 lock_share_entry( cnum, dev, inode, &token);
1273 del_share_mode(token, fnum);
1276 fd_attempt_close(fs_p->fd_ptr);
1278 if (lp_share_modes(SNUM(cnum)))
1279 unlock_share_entry( cnum, dev, inode, token);
1281 /* NT uses smbclose to start a print - weird */
1282 if (fs_p->print_file)
1283 print_file(fnum);
1285 /* check for magic scripts */
1286 check_magic(fnum,cnum);
1288 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1289 timestring(),Connections[cnum].user,fs_p->name,
1290 Connections[cnum].num_files_open));
1293 enum {AFAIL,AREAD,AWRITE,AALL};
1295 /*******************************************************************
1296 reproduce the share mode access table
1297 ********************************************************************/
1298 static int access_table(int new_deny,int old_deny,int old_mode,
1299 int share_pid,char *fname)
1301 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1303 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1304 if (old_deny == new_deny && share_pid == getpid())
1305 return(AALL);
1307 if (old_mode == 0) return(AREAD);
1309 /* the new smbpub.zip spec says that if the file extension is
1310 .com, .dll, .exe or .sym then allow the open. I will force
1311 it to read-only as this seems sensible although the spec is
1312 a little unclear on this. */
1313 if ((fname = strrchr(fname,'.'))) {
1314 if (strequal(fname,".com") ||
1315 strequal(fname,".dll") ||
1316 strequal(fname,".exe") ||
1317 strequal(fname,".sym"))
1318 return(AREAD);
1321 return(AFAIL);
1324 switch (new_deny)
1326 case DENY_WRITE:
1327 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1328 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1329 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1330 return(AFAIL);
1331 case DENY_READ:
1332 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1333 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1334 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1335 return(AFAIL);
1336 case DENY_NONE:
1337 if (old_deny==DENY_WRITE) return(AREAD);
1338 if (old_deny==DENY_READ) return(AWRITE);
1339 if (old_deny==DENY_NONE) return(AALL);
1340 return(AFAIL);
1342 return(AFAIL);
1345 /*******************************************************************
1346 check if the share mode on a file allows it to be deleted or unlinked
1347 return True if sharing doesn't prevent the operation
1348 ********************************************************************/
1349 BOOL check_file_sharing(int cnum,char *fname)
1351 int i;
1352 int ret = False;
1353 min_share_mode_entry *old_shares = 0;
1354 int num_share_modes;
1355 struct stat sbuf;
1356 share_lock_token token;
1357 int pid = getpid();
1359 if(!lp_share_modes(SNUM(cnum)))
1360 return True;
1362 if (stat(fname,&sbuf) == -1) return(True);
1364 lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token);
1365 num_share_modes = get_share_modes(cnum, token,
1366 (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares);
1368 for( i = 0; i < num_share_modes; i++)
1370 if (old_shares[i].share_mode != DENY_DOS)
1371 goto free_and_exit;
1373 if(old_shares[i].pid != pid)
1374 goto free_and_exit;
1377 /* XXXX exactly what share mode combinations should be allowed for
1378 deleting/renaming? */
1379 /* If we got here then either there were no share modes or
1380 all share modes were DENY_DOS and the pid == getpid() */
1381 ret = True;
1383 free_and_exit:
1385 unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token);
1386 if(old_shares != NULL)
1387 free((char *)old_shares);
1388 return(ret);
1391 /****************************************************************************
1392 C. Hoch 11/22/95
1393 Helper for open_file_shared.
1394 Truncate a file after checking locking; close file if locked.
1395 **************************************************************************/
1396 static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
1397 BOOL *share_locked)
1399 if (Files[fnum].can_write){
1400 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1401 /* If share modes are in force for this connection we
1402 have the share entry locked. Unlock it before closing. */
1403 if (*share_locked && lp_share_modes(SNUM(cnum)))
1404 unlock_share_entry( cnum, Files[fnum].fd_ptr->dev,
1405 Files[fnum].fd_ptr->inode, token);
1406 close_file(fnum);
1407 /* Share mode no longer locked. */
1408 *share_locked = False;
1409 errno = EACCES;
1410 unix_ERR_class = ERRDOS;
1411 unix_ERR_code = ERRlock;
1413 else
1414 ftruncate(Files[fnum].fd_ptr->fd,0);
1419 /****************************************************************************
1420 open a file with a share mode
1421 ****************************************************************************/
1422 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1423 int mode,int *Access,int *action)
1425 files_struct *fs_p = &Files[fnum];
1426 int flags=0;
1427 int flags2=0;
1428 int deny_mode = (share_mode>>4)&7;
1429 struct stat sbuf;
1430 BOOL file_existed = file_exist(fname,&sbuf);
1431 BOOL share_locked = False;
1432 BOOL fcbopen = False;
1433 share_lock_token token;
1434 uint32 dev = 0;
1435 uint32 inode = 0;
1437 fs_p->open = False;
1438 fs_p->fd_ptr = 0;
1440 /* this is for OS/2 EAs - try and say we don't support them */
1441 if (strstr(fname,".+,;=[]."))
1443 unix_ERR_class = ERRDOS;
1444 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1445 return;
1448 if ((ofun & 0x3) == 0 && file_existed)
1450 errno = EEXIST;
1451 return;
1454 if (ofun & 0x10)
1455 flags2 |= O_CREAT;
1456 if ((ofun & 0x3) == 2)
1457 flags2 |= O_TRUNC;
1459 /* note that we ignore the append flag as
1460 append does not mean the same thing under dos and unix */
1462 switch (share_mode&0xF)
1464 case 1:
1465 flags = O_WRONLY;
1466 break;
1467 case 0xF:
1468 fcbopen = True;
1469 flags = O_RDWR;
1470 break;
1471 case 2:
1472 flags = O_RDWR;
1473 break;
1474 default:
1475 flags = O_RDONLY;
1476 break;
1479 if (flags != O_RDONLY && file_existed &&
1480 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf))))
1482 if (!fcbopen)
1484 errno = EACCES;
1485 return;
1487 flags = O_RDONLY;
1490 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB)
1492 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1493 errno = EINVAL;
1494 return;
1497 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1499 if (lp_share_modes(SNUM(cnum)))
1501 int num_shares = 0;
1502 int i;
1503 min_share_mode_entry *old_shares = 0;
1506 if (file_existed)
1508 dev = (uint32)sbuf.st_dev;
1509 inode = (uint32)sbuf.st_ino;
1510 lock_share_entry(cnum, dev, inode, &token);
1511 share_locked = True;
1512 num_shares = get_share_modes(cnum, token, dev, inode, &old_shares);
1515 for(i = 0; i < num_shares; i++)
1517 /* someone else has a share lock on it, check to see
1518 if we can too */
1519 int old_open_mode = old_shares[i].share_mode &0xF;
1520 int old_deny_mode = (old_shares[i].share_mode >>4)&7;
1522 if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2)
1524 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1525 deny_mode,old_deny_mode,old_open_mode,fname));
1526 free((char *)old_shares);
1527 if(share_locked)
1528 unlock_share_entry(cnum, dev, inode, token);
1529 errno = EACCES;
1530 unix_ERR_class = ERRDOS;
1531 unix_ERR_code = ERRbadshare;
1532 return;
1536 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1537 old_shares[i].pid,fname);
1539 if ((access_allowed == AFAIL) ||
1540 (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
1541 (access_allowed == AREAD && flags == O_WRONLY) ||
1542 (access_allowed == AWRITE && flags == O_RDONLY))
1544 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1545 deny_mode,old_deny_mode,old_open_mode,
1546 old_shares[i].pid,fname,
1547 access_allowed));
1548 free((char *)old_shares);
1549 if(share_locked)
1550 unlock_share_entry(cnum, dev, inode, token);
1551 errno = EACCES;
1552 unix_ERR_class = ERRDOS;
1553 unix_ERR_code = ERRbadshare;
1554 return;
1557 if (access_allowed == AREAD)
1558 flags = O_RDONLY;
1560 if (access_allowed == AWRITE)
1561 flags = O_WRONLY;
1564 if(old_shares != 0)
1565 free((char *)old_shares);
1568 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1569 flags,flags2,mode));
1571 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1572 if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
1574 flags = O_RDONLY;
1575 open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1578 if (fs_p->open)
1580 int open_mode=0;
1582 if((share_locked == False) && lp_share_modes(SNUM(cnum)))
1584 /* We created the file - thus we must now lock the share entry before creating it. */
1585 dev = fs_p->fd_ptr->dev;
1586 inode = fs_p->fd_ptr->inode;
1587 lock_share_entry(cnum, dev, inode, &token);
1588 share_locked = True;
1591 switch (flags)
1593 case O_RDONLY:
1594 open_mode = 0;
1595 break;
1596 case O_RDWR:
1597 open_mode = 2;
1598 break;
1599 case O_WRONLY:
1600 open_mode = 1;
1601 break;
1604 fs_p->share_mode = (deny_mode<<4) | open_mode;
1606 if (Access)
1607 (*Access) = open_mode;
1609 if (action)
1611 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1612 if (!file_existed) *action = 2;
1613 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1615 /* We must create the share mode entry before truncate as
1616 truncate can fail due to locking and have to close the
1617 file (which expects the share_mode_entry to be there).
1619 if (lp_share_modes(SNUM(cnum)))
1620 set_share_mode(token, fnum);
1622 if ((flags2&O_TRUNC) && file_existed)
1623 truncate_unless_locked(fnum,cnum,token,&share_locked);
1626 if (share_locked && lp_share_modes(SNUM(cnum)))
1627 unlock_share_entry( cnum, dev, inode, token);
1630 /****************************************************************************
1631 seek a file. Try to avoid the seek if possible
1632 ****************************************************************************/
1633 int seek_file(int fnum,int pos)
1635 int offset = 0;
1636 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1637 offset = 3;
1639 Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset;
1640 return(Files[fnum].pos);
1643 /****************************************************************************
1644 read from a file
1645 ****************************************************************************/
1646 int read_file(int fnum,char *data,int pos,int n)
1648 int ret=0,readret;
1650 if (!Files[fnum].can_write)
1652 ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1654 data += ret;
1655 n -= ret;
1656 pos += ret;
1659 #if USE_MMAP
1660 if (Files[fnum].mmap_ptr)
1662 int num = MIN(n,Files[fnum].mmap_size-pos);
1663 if (num > 0)
1665 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1666 data += num;
1667 pos += num;
1668 n -= num;
1669 ret += num;
1672 #endif
1674 if (n <= 0)
1675 return(ret);
1677 if (seek_file(fnum,pos) != pos)
1679 DEBUG(3,("Failed to seek to %d\n",pos));
1680 return(ret);
1683 if (n > 0) {
1684 readret = read(Files[fnum].fd_ptr->fd,data,n);
1685 if (readret > 0) ret += readret;
1688 return(ret);
1692 /****************************************************************************
1693 write to a file
1694 ****************************************************************************/
1695 int write_file(int fnum,char *data,int n)
1697 if (!Files[fnum].can_write) {
1698 errno = EPERM;
1699 return(0);
1702 if (!Files[fnum].modified) {
1703 struct stat st;
1704 Files[fnum].modified = True;
1705 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1706 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1707 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
1708 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1713 return(write_data(Files[fnum].fd_ptr->fd,data,n));
1717 /****************************************************************************
1718 load parameters specific to a connection/service
1719 ****************************************************************************/
1720 BOOL become_service(int cnum,BOOL do_chdir)
1722 extern char magic_char;
1723 static int last_cnum = -1;
1724 int snum;
1726 if (!OPEN_CNUM(cnum))
1728 last_cnum = -1;
1729 return(False);
1732 Connections[cnum].lastused = smb_last_time;
1734 snum = SNUM(cnum);
1736 if (do_chdir &&
1737 ChDir(Connections[cnum].connectpath) != 0 &&
1738 ChDir(Connections[cnum].origpath) != 0)
1740 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1741 Connections[cnum].connectpath,cnum));
1742 return(False);
1745 if (cnum == last_cnum)
1746 return(True);
1748 last_cnum = cnum;
1750 case_default = lp_defaultcase(snum);
1751 case_preserve = lp_preservecase(snum);
1752 short_case_preserve = lp_shortpreservecase(snum);
1753 case_mangle = lp_casemangle(snum);
1754 case_sensitive = lp_casesensitive(snum);
1755 magic_char = lp_magicchar(snum);
1756 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1757 return(True);
1761 /****************************************************************************
1762 find a service entry
1763 ****************************************************************************/
1764 int find_service(char *service)
1766 int iService;
1768 string_sub(service,"\\","/");
1770 iService = lp_servicenumber(service);
1772 /* now handle the special case of a home directory */
1773 if (iService < 0)
1775 char *phome_dir = get_home_dir(service);
1776 DEBUG(3,("checking for home directory %s gave %s\n",service,
1777 phome_dir?phome_dir:"(NULL)"));
1778 if (phome_dir)
1780 int iHomeService;
1781 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1783 lp_add_home(service,iHomeService,phome_dir);
1784 iService = lp_servicenumber(service);
1789 /* If we still don't have a service, attempt to add it as a printer. */
1790 if (iService < 0)
1792 int iPrinterService;
1794 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1796 char *pszTemp;
1798 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1799 pszTemp = PRINTCAP;
1800 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1802 DEBUG(3,("%s is a valid printer name\n", service));
1803 DEBUG(3,("adding %s as a printer service\n", service));
1804 lp_add_printer(service,iPrinterService);
1805 iService = lp_servicenumber(service);
1806 if (iService < 0)
1807 DEBUG(0,("failed to add %s as a printer service!\n", service));
1809 else
1810 DEBUG(3,("%s is not a valid printer name\n", service));
1814 /* just possibly it's a default service? */
1815 if (iService < 0)
1817 char *defservice = lp_defaultservice();
1818 if (defservice && *defservice && !strequal(defservice,service)) {
1819 iService = find_service(defservice);
1820 if (iService >= 0) {
1821 string_sub(service,"_","/");
1822 iService = lp_add_service(service,iService);
1827 if (iService >= 0)
1828 if (!VALID_SNUM(iService))
1830 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1831 iService = -1;
1834 if (iService < 0)
1835 DEBUG(3,("find_service() failed to find service %s\n", service));
1837 return (iService);
1841 /****************************************************************************
1842 create an error packet from a cached error.
1843 ****************************************************************************/
1844 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1846 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1848 int32 eclass = wbmpx->wr_errclass;
1849 int32 err = wbmpx->wr_error;
1851 /* We can now delete the auxiliary struct */
1852 free((char *)wbmpx);
1853 Files[fnum].wbmpx_ptr = NULL;
1854 return error_packet(inbuf,outbuf,eclass,err,line);
1858 struct
1860 int unixerror;
1861 int smbclass;
1862 int smbcode;
1863 } unix_smb_errmap[] =
1865 {EPERM,ERRDOS,ERRnoaccess},
1866 {EACCES,ERRDOS,ERRnoaccess},
1867 {ENOENT,ERRDOS,ERRbadfile},
1868 {EIO,ERRHRD,ERRgeneral},
1869 {EBADF,ERRSRV,ERRsrverror},
1870 {EINVAL,ERRSRV,ERRsrverror},
1871 {EEXIST,ERRDOS,ERRfilexists},
1872 {ENFILE,ERRDOS,ERRnofids},
1873 {EMFILE,ERRDOS,ERRnofids},
1874 {ENOSPC,ERRHRD,ERRdiskfull},
1875 #ifdef EDQUOT
1876 {EDQUOT,ERRHRD,ERRdiskfull},
1877 #endif
1878 #ifdef ENOTEMPTY
1879 {ENOTEMPTY,ERRDOS,ERRnoaccess},
1880 #endif
1881 #ifdef EXDEV
1882 {EXDEV,ERRDOS,ERRdiffdevice},
1883 #endif
1884 {EROFS,ERRHRD,ERRnowrite},
1885 {0,0,0}
1889 /****************************************************************************
1890 create an error packet from errno
1891 ****************************************************************************/
1892 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1894 int eclass=def_class;
1895 int ecode=def_code;
1896 int i=0;
1898 if (unix_ERR_class != SUCCESS)
1900 eclass = unix_ERR_class;
1901 ecode = unix_ERR_code;
1902 unix_ERR_class = SUCCESS;
1903 unix_ERR_code = 0;
1905 else
1907 while (unix_smb_errmap[i].smbclass != 0)
1909 if (unix_smb_errmap[i].unixerror == errno)
1911 eclass = unix_smb_errmap[i].smbclass;
1912 ecode = unix_smb_errmap[i].smbcode;
1913 break;
1915 i++;
1919 return(error_packet(inbuf,outbuf,eclass,ecode,line));
1923 /****************************************************************************
1924 create an error packet. Normally called using the ERROR() macro
1925 ****************************************************************************/
1926 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1928 int outsize = set_message(outbuf,0,0,True);
1929 int cmd;
1930 cmd = CVAL(inbuf,smb_com);
1932 CVAL(outbuf,smb_rcls) = error_class;
1933 SSVAL(outbuf,smb_err,error_code);
1935 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1936 timestring(),
1937 line,
1938 (int)CVAL(inbuf,smb_com),
1939 smb_fn_name(CVAL(inbuf,smb_com)),
1940 error_class,
1941 error_code));
1943 if (errno != 0)
1944 DEBUG(3,("error string = %s\n",strerror(errno)));
1946 return(outsize);
1950 #ifndef SIGCLD_IGNORE
1951 /****************************************************************************
1952 this prevents zombie child processes
1953 ****************************************************************************/
1954 static int sig_cld()
1956 static int depth = 0;
1957 if (depth != 0)
1959 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1960 depth=0;
1961 return(0);
1963 depth++;
1965 BlockSignals(True,SIGCLD);
1966 DEBUG(5,("got SIGCLD\n"));
1968 #ifdef USE_WAITPID
1969 while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
1970 #endif
1972 /* Stop zombies */
1973 /* Stevens, Adv. Unix Prog. says that on system V you must call
1974 wait before reinstalling the signal handler, because the kernel
1975 calls the handler from within the signal-call when there is a
1976 child that has exited. This would lead to an infinite recursion
1977 if done vice versa. */
1979 #ifndef DONT_REINSTALL_SIG
1980 #ifdef SIGCLD_IGNORE
1981 signal(SIGCLD, SIG_IGN);
1982 #else
1983 signal(SIGCLD, SIGNAL_CAST sig_cld);
1984 #endif
1985 #endif
1987 #ifndef USE_WAITPID
1988 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
1989 #endif
1990 depth--;
1991 BlockSignals(False,SIGCLD);
1992 return 0;
1994 #endif
1996 /****************************************************************************
1997 this is called when the client exits abruptly
1998 **************************************************************************/
1999 static int sig_pipe()
2001 extern int password_client;
2002 BlockSignals(True,SIGPIPE);
2004 if (password_client != -1) {
2005 DEBUG(3,("lost connection to password server\n"));
2006 close(password_client);
2007 password_client = -1;
2008 #ifndef DONT_REINSTALL_SIG
2009 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2010 #endif
2011 BlockSignals(False,SIGPIPE);
2012 return 0;
2015 exit_server("Got sigpipe\n");
2016 return(0);
2019 /****************************************************************************
2020 open the socket communication
2021 ****************************************************************************/
2022 static BOOL open_sockets(BOOL is_daemon,int port)
2024 extern int Client;
2026 if (is_daemon)
2028 int s;
2029 struct sockaddr addr;
2030 int in_addrlen = sizeof(addr);
2032 /* Stop zombies */
2033 #ifdef SIGCLD_IGNORE
2034 signal(SIGCLD, SIG_IGN);
2035 #else
2036 signal(SIGCLD, SIGNAL_CAST sig_cld);
2037 #endif
2039 /* open an incoming socket */
2040 s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
2041 if (s == -1)
2042 return(False);
2044 /* ready to listen */
2045 if (listen(s, 5) == -1)
2047 DEBUG(0,("listen: %s",strerror(errno)));
2048 close(s);
2049 return False;
2052 if(atexit_set == 0)
2053 atexit(killkids);
2055 /* now accept incoming connections - forking a new process
2056 for each incoming connection */
2057 DEBUG(2,("waiting for a connection\n"));
2058 while (1)
2060 Client = accept(s,&addr,&in_addrlen);
2062 if (Client == -1 && errno == EINTR)
2063 continue;
2065 if (Client == -1)
2067 DEBUG(0,("accept: %s",strerror(errno)));
2068 continue;
2071 #ifdef NO_FORK_DEBUG
2072 #ifndef NO_SIGNAL_TEST
2073 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2074 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2075 #endif
2076 return True;
2077 #else
2078 if (Client != -1 && fork()==0)
2080 /* Child code ... */
2081 #ifndef NO_SIGNAL_TEST
2082 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2083 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2084 #endif
2085 /* close the listening socket */
2086 close(s);
2088 /* close our standard file descriptors */
2089 close_low_fds();
2090 am_parent = 0;
2092 set_socket_options(Client,"SO_KEEPALIVE");
2093 set_socket_options(Client,user_socket_options);
2095 /* Reset global variables in util.c so that
2096 client substitutions will be done correctly
2097 in the process.
2099 reset_globals_after_fork();
2100 return True;
2102 close(Client); /* The parent doesn't need this socket */
2103 #endif
2106 else
2108 /* We will abort gracefully when the client or remote system
2109 goes away */
2110 #ifndef NO_SIGNAL_TEST
2111 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2112 #endif
2113 Client = dup(0);
2115 /* close our standard file descriptors */
2116 close_low_fds();
2118 set_socket_options(Client,"SO_KEEPALIVE");
2119 set_socket_options(Client,user_socket_options);
2122 return True;
2126 /****************************************************************************
2127 check if a snum is in use
2128 ****************************************************************************/
2129 BOOL snum_used(int snum)
2131 int i;
2132 for (i=0;i<MAX_CONNECTIONS;i++)
2133 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2134 return(True);
2135 return(False);
2138 /****************************************************************************
2139 reload the services file
2140 **************************************************************************/
2141 BOOL reload_services(BOOL test)
2143 BOOL ret;
2145 if (lp_loaded())
2147 pstring fname;
2148 strcpy(fname,lp_configfile());
2149 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2151 strcpy(servicesf,fname);
2152 test = False;
2156 reopen_logs();
2158 if (test && !lp_file_list_changed())
2159 return(True);
2161 lp_killunused(snum_used);
2163 ret = lp_load(servicesf,False);
2165 /* perhaps the config filename is now set */
2166 if (!test)
2167 reload_services(True);
2169 reopen_logs();
2171 load_interfaces();
2174 extern int Client;
2175 if (Client != -1) {
2176 set_socket_options(Client,"SO_KEEPALIVE");
2177 set_socket_options(Client,user_socket_options);
2181 create_mangled_stack(lp_mangledstack());
2183 /* this forces service parameters to be flushed */
2184 become_service(-1,True);
2186 return(ret);
2191 /****************************************************************************
2192 this prevents zombie child processes
2193 ****************************************************************************/
2194 static int sig_hup()
2196 BlockSignals(True,SIGHUP);
2197 DEBUG(0,("Got SIGHUP\n"));
2198 reload_services(False);
2199 #ifndef DONT_REINSTALL_SIG
2200 signal(SIGHUP,SIGNAL_CAST sig_hup);
2201 #endif
2202 BlockSignals(False,SIGHUP);
2203 return(0);
2206 /****************************************************************************
2207 Setup the groups a user belongs to.
2208 ****************************************************************************/
2209 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
2210 int **p_igroups, gid_t **p_groups)
2212 if (-1 == initgroups(user,gid))
2214 if (getuid() == 0)
2216 DEBUG(0,("Unable to initgroups!\n"));
2217 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2218 DEBUG(0,("This is probably a problem with the account %s\n",user));
2221 else
2223 int i,ngroups;
2224 int *igroups;
2225 gid_t grp = 0;
2226 ngroups = getgroups(0,&grp);
2227 if (ngroups <= 0)
2228 ngroups = 32;
2229 igroups = (int *)malloc(sizeof(int)*ngroups);
2230 for (i=0;i<ngroups;i++)
2231 igroups[i] = 0x42424242;
2232 ngroups = getgroups(ngroups,(gid_t *)igroups);
2234 if (igroups[0] == 0x42424242)
2235 ngroups = 0;
2237 *p_ngroups = ngroups;
2239 /* The following bit of code is very strange. It is due to the
2240 fact that some OSes use int* and some use gid_t* for
2241 getgroups, and some (like SunOS) use both, one in prototypes,
2242 and one in man pages and the actual code. Thus we detect it
2243 dynamically using some very ugly code */
2244 if (ngroups > 0)
2246 /* does getgroups return ints or gid_t ?? */
2247 static BOOL groups_use_ints = True;
2249 if (groups_use_ints &&
2250 ngroups == 1 &&
2251 SVAL(igroups,2) == 0x4242)
2252 groups_use_ints = False;
2254 for (i=0;groups_use_ints && i<ngroups;i++)
2255 if (igroups[i] == 0x42424242)
2256 groups_use_ints = False;
2258 if (groups_use_ints)
2260 *p_igroups = igroups;
2261 *p_groups = (gid_t *)igroups;
2263 else
2265 gid_t *groups = (gid_t *)igroups;
2266 igroups = (int *)malloc(sizeof(int)*ngroups);
2267 for (i=0;i<ngroups;i++)
2268 igroups[i] = groups[i];
2269 *p_igroups = igroups;
2270 *p_groups = (gid_t *)groups;
2273 DEBUG(3,("%s is in %d groups\n",user,ngroups));
2274 for (i=0;i<ngroups;i++)
2275 DEBUG(3,("%d ",igroups[i]));
2276 DEBUG(3,("\n"));
2278 return 0;
2281 /****************************************************************************
2282 make a connection to a service
2283 ****************************************************************************/
2284 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2286 int cnum;
2287 int snum;
2288 struct passwd *pass = NULL;
2289 connection_struct *pcon;
2290 BOOL guest = False;
2291 BOOL force = False;
2292 static BOOL first_connection = True;
2294 strlower(service);
2296 snum = find_service(service);
2297 if (snum < 0)
2299 if (strequal(service,"IPC$"))
2301 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2302 return(-3);
2305 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2306 return(-2);
2309 if (strequal(service,HOMES_NAME))
2311 if (*user && Get_Pwnam(user,True))
2312 return(make_connection(user,user,password,pwlen,dev,vuid));
2314 if (validated_username(vuid))
2316 strcpy(user,validated_username(vuid));
2317 return(make_connection(user,user,password,pwlen,dev,vuid));
2321 if (!lp_snum_ok(snum) || !check_access(snum)) {
2322 return(-4);
2325 /* you can only connect to the IPC$ service as an ipc device */
2326 if (strequal(service,"IPC$"))
2327 strcpy(dev,"IPC");
2329 if (*dev == '?' || !*dev)
2331 if (lp_print_ok(snum))
2332 strcpy(dev,"LPT1:");
2333 else
2334 strcpy(dev,"A:");
2337 /* if the request is as a printer and you can't print then refuse */
2338 strupper(dev);
2339 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2340 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2341 return(-6);
2344 /* lowercase the user name */
2345 strlower(user);
2347 /* add it as a possible user name */
2348 add_session_user(service);
2350 /* shall we let them in? */
2351 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2353 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2354 return(-1);
2357 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2358 if (cnum < 0)
2360 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2361 return(-1);
2364 pcon = &Connections[cnum];
2365 bzero((char *)pcon,sizeof(*pcon));
2367 /* find out some info about the user */
2368 pass = Get_Pwnam(user,True);
2370 if (pass == NULL)
2372 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2373 return(-7);
2376 pcon->read_only = lp_readonly(snum);
2379 pstring list;
2380 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2381 string_sub(list,"%S",service);
2383 if (user_in_list(user,list))
2384 pcon->read_only = True;
2386 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2387 string_sub(list,"%S",service);
2389 if (user_in_list(user,list))
2390 pcon->read_only = False;
2393 /* admin user check */
2394 if (user_in_list(user,lp_admin_users(snum)) &&
2395 !pcon->read_only)
2397 pcon->admin_user = True;
2398 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2400 else
2401 pcon->admin_user = False;
2403 pcon->force_user = force;
2404 pcon->vuid = vuid;
2405 pcon->uid = pass->pw_uid;
2406 pcon->gid = pass->pw_gid;
2407 pcon->num_files_open = 0;
2408 pcon->lastused = time(NULL);
2409 pcon->service = snum;
2410 pcon->used = True;
2411 pcon->printer = (strncmp(dev,"LPT",3) == 0);
2412 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2413 pcon->dirptr = NULL;
2414 string_set(&pcon->dirpath,"");
2415 string_set(&pcon->user,user);
2417 #if HAVE_GETGRNAM
2418 if (*lp_force_group(snum))
2420 struct group *gptr;
2421 pstring gname;
2423 StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2424 /* default service may be a group name */
2425 string_sub(gname,"%S",service);
2426 gptr = (struct group *)getgrnam(gname);
2428 if (gptr)
2430 pcon->gid = gptr->gr_gid;
2431 DEBUG(3,("Forced group %s\n",gname));
2433 else
2434 DEBUG(1,("Couldn't find group %s\n",gname));
2436 #endif
2438 if (*lp_force_user(snum))
2440 struct passwd *pass2;
2441 fstring fuser;
2442 strcpy(fuser,lp_force_user(snum));
2443 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2444 if (pass2)
2446 pcon->uid = pass2->pw_uid;
2447 string_set(&pcon->user,fuser);
2448 strcpy(user,fuser);
2449 pcon->force_user = True;
2450 DEBUG(3,("Forced user %s\n",fuser));
2452 else
2453 DEBUG(1,("Couldn't find user %s\n",fuser));
2457 pstring s;
2458 strcpy(s,lp_pathname(snum));
2459 standard_sub(cnum,s);
2460 string_set(&pcon->connectpath,s);
2461 DEBUG(3,("Connect path is %s\n",s));
2464 /* groups stuff added by ih */
2465 pcon->ngroups = 0;
2466 pcon->groups = NULL;
2468 if (!IS_IPC(cnum))
2470 /* Find all the groups this uid is in and store them. Used by become_user() */
2471 setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2473 /* check number of connections */
2474 if (!claim_connection(cnum,
2475 lp_servicename(SNUM(cnum)),
2476 lp_max_connections(SNUM(cnum)),False))
2478 DEBUG(1,("too many connections - rejected\n"));
2479 return(-8);
2482 if (lp_status(SNUM(cnum)))
2483 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2485 first_connection = False;
2486 } /* IS_IPC */
2488 pcon->open = True;
2490 /* execute any "root preexec = " line */
2491 if (*lp_rootpreexec(SNUM(cnum)))
2493 pstring cmd;
2494 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2495 standard_sub(cnum,cmd);
2496 DEBUG(5,("cmd=%s\n",cmd));
2497 smbrun(cmd,NULL,False);
2500 if (!become_user(cnum,pcon->vuid))
2502 DEBUG(0,("Can't become connected user!\n"));
2503 pcon->open = False;
2504 if (!IS_IPC(cnum)) {
2505 yield_connection(cnum,
2506 lp_servicename(SNUM(cnum)),
2507 lp_max_connections(SNUM(cnum)));
2508 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2510 return(-1);
2513 if (ChDir(pcon->connectpath) != 0)
2515 DEBUG(0,("Can't change directory to %s (%s)\n",
2516 pcon->connectpath,strerror(errno)));
2517 pcon->open = False;
2518 unbecome_user();
2519 if (!IS_IPC(cnum)) {
2520 yield_connection(cnum,
2521 lp_servicename(SNUM(cnum)),
2522 lp_max_connections(SNUM(cnum)));
2523 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2525 return(-5);
2528 string_set(&pcon->origpath,pcon->connectpath);
2530 #if SOFTLINK_OPTIMISATION
2531 /* resolve any soft links early */
2533 pstring s;
2534 strcpy(s,pcon->connectpath);
2535 GetWd(s);
2536 string_set(&pcon->connectpath,s);
2537 ChDir(pcon->connectpath);
2539 #endif
2541 num_connections_open++;
2542 add_session_user(user);
2544 /* execute any "preexec = " line */
2545 if (*lp_preexec(SNUM(cnum)))
2547 pstring cmd;
2548 strcpy(cmd,lp_preexec(SNUM(cnum)));
2549 standard_sub(cnum,cmd);
2550 smbrun(cmd,NULL,False);
2553 /* we've finished with the sensitive stuff */
2554 unbecome_user();
2557 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2558 timestring(),
2559 remote_machine,
2560 client_addr(),
2561 lp_servicename(SNUM(cnum)),user,
2562 pcon->uid,
2563 pcon->gid,
2564 (int)getpid()));
2567 return(cnum);
2571 /****************************************************************************
2572 find first available file slot
2573 ****************************************************************************/
2574 int find_free_file(void )
2576 int i;
2577 /* we start at 1 here for an obscure reason I can't now remember,
2578 but I think is important :-) */
2579 for (i=1;i<MAX_OPEN_FILES;i++)
2580 if (!Files[i].open)
2581 return(i);
2582 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2583 return(-1);
2586 /****************************************************************************
2587 find first available connection slot, starting from a random position.
2588 The randomisation stops problems with the server dieing and clients
2589 thinking the server is still available.
2590 ****************************************************************************/
2591 static int find_free_connection(int hash )
2593 int i;
2594 BOOL used=False;
2595 hash = (hash % (MAX_CONNECTIONS-2))+1;
2597 again:
2599 for (i=hash+1;i!=hash;)
2601 if (!Connections[i].open && Connections[i].used == used)
2603 DEBUG(3,("found free connection number %d\n",i));
2604 return(i);
2606 i++;
2607 if (i == MAX_CONNECTIONS)
2608 i = 1;
2611 if (!used)
2613 used = !used;
2614 goto again;
2617 DEBUG(1,("ERROR! Out of connection structures\n"));
2618 return(-1);
2622 /****************************************************************************
2623 reply for the core protocol
2624 ****************************************************************************/
2625 int reply_corep(char *outbuf)
2627 int outsize = set_message(outbuf,1,0,True);
2629 Protocol = PROTOCOL_CORE;
2631 return outsize;
2635 /****************************************************************************
2636 reply for the coreplus protocol
2637 ****************************************************************************/
2638 int reply_coreplus(char *outbuf)
2640 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2641 int outsize = set_message(outbuf,13,0,True);
2642 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2643 readbraw and writebraw (possibly) */
2644 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2645 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
2647 Protocol = PROTOCOL_COREPLUS;
2649 return outsize;
2653 /****************************************************************************
2654 reply for the lanman 1.0 protocol
2655 ****************************************************************************/
2656 int reply_lanman1(char *outbuf)
2658 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2659 int secword=0;
2660 BOOL doencrypt = SMBENCRYPT();
2661 time_t t = time(NULL);
2662 /* We need to save and restore this as it can be destroyed
2663 if we call another server if security=server
2664 Thanks to Paul Nelson @ Thursby for pointing this out.
2666 uint16 mid = SVAL(outbuf, smb_mid);
2668 if (lp_security()>=SEC_USER) secword |= 1;
2669 if (doencrypt) secword |= 2;
2671 set_message(outbuf,13,doencrypt?8:0,True);
2672 SSVAL(outbuf,smb_vwv1,secword);
2673 #ifdef SMB_PASSWD
2674 /* Create a token value and add it to the outgoing packet. */
2675 if (doencrypt)
2676 generate_next_challenge(smb_buf(outbuf));
2677 #endif
2679 Protocol = PROTOCOL_LANMAN1;
2681 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2682 DEBUG(3,("using password server validation\n"));
2683 #ifdef SMB_PASSWD
2684 if (doencrypt) set_challenge(smb_buf(outbuf));
2685 #endif
2688 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2689 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2690 SSVAL(outbuf,smb_vwv2,max_recv);
2691 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2692 SSVAL(outbuf,smb_vwv4,1);
2693 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2694 readbraw writebraw (possibly) */
2695 SIVAL(outbuf,smb_vwv6,getpid());
2696 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2698 put_dos_date(outbuf,smb_vwv8,t);
2700 return (smb_len(outbuf)+4);
2704 /****************************************************************************
2705 reply for the lanman 2.0 protocol
2706 ****************************************************************************/
2707 int reply_lanman2(char *outbuf)
2709 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2710 int secword=0;
2711 BOOL doencrypt = SMBENCRYPT();
2712 time_t t = time(NULL);
2713 /* We need to save and restore this as it can be destroyed
2714 if we call another server if security=server
2715 Thanks to Paul Nelson @ Thursby for pointing this out.
2717 uint16 mid = SVAL(outbuf, smb_mid);
2719 if (lp_security()>=SEC_USER) secword |= 1;
2720 if (doencrypt) secword |= 2;
2722 set_message(outbuf,13,doencrypt?8:0,True);
2723 SSVAL(outbuf,smb_vwv1,secword);
2724 #ifdef SMB_PASSWD
2725 /* Create a token value and add it to the outgoing packet. */
2726 if (doencrypt)
2727 generate_next_challenge(smb_buf(outbuf));
2728 #endif
2730 SIVAL(outbuf,smb_vwv6,getpid());
2732 Protocol = PROTOCOL_LANMAN2;
2734 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2735 DEBUG(3,("using password server validation\n"));
2736 #ifdef SMB_PASSWD
2737 if (doencrypt) set_challenge(smb_buf(outbuf));
2738 #endif
2741 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2742 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2743 SSVAL(outbuf,smb_vwv2,max_recv);
2744 SSVAL(outbuf,smb_vwv3,lp_maxmux());
2745 SSVAL(outbuf,smb_vwv4,1);
2746 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2747 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2748 put_dos_date(outbuf,smb_vwv8,t);
2750 return (smb_len(outbuf)+4);
2754 /****************************************************************************
2755 reply for the nt protocol
2756 ****************************************************************************/
2757 int reply_nt1(char *outbuf)
2759 /* dual names + lock_and_read + nt SMBs + remote API calls */
2760 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
2762 other valid capabilities which we may support at some time...
2763 CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
2764 CAP_LARGE_FILES|CAP_LARGE_READX|
2765 CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
2768 int secword=0;
2769 BOOL doencrypt = SMBENCRYPT();
2770 time_t t = time(NULL);
2771 int data_len;
2772 int encrypt_len;
2773 char challenge_len = 8;
2774 /* We need to save and restore this as it can be destroyed
2775 if we call another server if security=server
2776 Thanks to Paul Nelson @ Thursby for pointing this out.
2778 uint16 mid = SVAL(outbuf, smb_mid);
2780 if (lp_readraw() && lp_writeraw())
2782 capabilities |= CAP_RAW_MODE;
2785 if (lp_security()>=SEC_USER) secword |= 1;
2786 if (doencrypt) secword |= 2;
2788 /* decide where (if) to put the encryption challenge, and
2789 follow it with the OEM'd domain name
2791 encrypt_len = doencrypt?challenge_len:0;
2792 #if UNICODE
2793 data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
2794 #else
2795 data_len = encrypt_len + strlen(myworkgroup) + 1;
2796 #endif
2798 set_message(outbuf,17,data_len,True);
2800 #if UNICODE
2801 /* put the OEM'd domain name */
2802 PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
2803 #else
2804 strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
2805 #endif
2807 CVAL(outbuf,smb_vwv1) = secword;
2808 #ifdef SMB_PASSWD
2809 /* Create a token value and add it to the outgoing packet. */
2810 if (doencrypt)
2812 generate_next_challenge(smb_buf(outbuf));
2814 /* Tell the nt machine how long the challenge is. */
2815 SSVALS(outbuf,smb_vwv16+1,challenge_len);
2817 #endif
2819 Protocol = PROTOCOL_NT1;
2821 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2822 DEBUG(3,("using password server validation\n"));
2823 #ifdef SMB_PASSWD
2824 if (doencrypt) set_challenge(smb_buf(outbuf));
2825 #endif
2828 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2829 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2830 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2831 SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
2832 SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
2833 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2834 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2835 put_long_date(outbuf+smb_vwv11+1,t);
2836 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2837 SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
2839 return (smb_len(outbuf)+4);
2842 /* these are the protocol lists used for auto architecture detection:
2844 WinNT 3.51:
2845 protocol [PC NETWORK PROGRAM 1.0]
2846 protocol [XENIX CORE]
2847 protocol [MICROSOFT NETWORKS 1.03]
2848 protocol [LANMAN1.0]
2849 protocol [Windows for Workgroups 3.1a]
2850 protocol [LM1.2X002]
2851 protocol [LANMAN2.1]
2852 protocol [NT LM 0.12]
2854 Win95:
2855 protocol [PC NETWORK PROGRAM 1.0]
2856 protocol [XENIX CORE]
2857 protocol [MICROSOFT NETWORKS 1.03]
2858 protocol [LANMAN1.0]
2859 protocol [Windows for Workgroups 3.1a]
2860 protocol [LM1.2X002]
2861 protocol [LANMAN2.1]
2862 protocol [NT LM 0.12]
2864 OS/2:
2865 protocol [PC NETWORK PROGRAM 1.0]
2866 protocol [XENIX CORE]
2867 protocol [LANMAN1.0]
2868 protocol [LM1.2X002]
2869 protocol [LANMAN2.1]
2873 * Modified to recognize the architecture of the remote machine better.
2875 * This appears to be the matrix of which protocol is used by which
2876 * MS product.
2877 Protocol WfWg Win95 WinNT OS/2
2878 PC NETWORK PROGRAM 1.0 1 1 1 1
2879 XENIX CORE 2 2
2880 MICROSOFT NETWORKS 3.0 2 2
2881 DOS LM1.2X002 3 3
2882 MICROSOFT NETWORKS 1.03 3
2883 DOS LANMAN2.1 4 4
2884 LANMAN1.0 4 3
2885 Windows for Workgroups 3.1a 5 5 5
2886 LM1.2X002 6 4
2887 LANMAN2.1 7 5
2888 NT LM 0.12 6 8
2890 * tim@fsg.com 09/29/95
2893 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2894 #define ARCH_WIN95 0x2
2895 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2896 #define ARCH_WINNT 0x8
2897 #define ARCH_SAMBA 0x10
2899 #define ARCH_ALL 0x1F
2901 /* List of supported protocols, most desired first */
2902 struct {
2903 char *proto_name;
2904 char *short_name;
2905 int (*proto_reply_fn)(char *);
2906 int protocol_level;
2907 } supported_protocols[] = {
2908 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
2909 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
2910 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2911 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2912 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
2913 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2914 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
2915 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2916 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
2917 {NULL,NULL},
2921 /****************************************************************************
2922 reply to a negprot
2923 ****************************************************************************/
2924 static int reply_negprot(char *inbuf,char *outbuf)
2926 extern fstring remote_arch;
2927 int outsize = set_message(outbuf,1,0,True);
2928 int Index=0;
2929 int choice= -1;
2930 int protocol;
2931 char *p;
2932 int bcc = SVAL(smb_buf(inbuf),-2);
2933 int arch = ARCH_ALL;
2935 p = smb_buf(inbuf)+1;
2936 while (p < (smb_buf(inbuf) + bcc))
2938 Index++;
2939 DEBUG(3,("Requested protocol [%s]\n",p));
2940 if (strcsequal(p,"Windows for Workgroups 3.1a"))
2941 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2942 else if (strcsequal(p,"DOS LM1.2X002"))
2943 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2944 else if (strcsequal(p,"DOS LANMAN2.1"))
2945 arch &= ( ARCH_WFWG | ARCH_WIN95 );
2946 else if (strcsequal(p,"NT LM 0.12"))
2947 arch &= ( ARCH_WIN95 | ARCH_WINNT );
2948 else if (strcsequal(p,"LANMAN2.1"))
2949 arch &= ( ARCH_WINNT | ARCH_OS2 );
2950 else if (strcsequal(p,"LM1.2X002"))
2951 arch &= ( ARCH_WINNT | ARCH_OS2 );
2952 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2953 arch &= ARCH_WINNT;
2954 else if (strcsequal(p,"XENIX CORE"))
2955 arch &= ( ARCH_WINNT | ARCH_OS2 );
2956 else if (strcsequal(p,"Samba")) {
2957 arch = ARCH_SAMBA;
2958 break;
2961 p += strlen(p) + 2;
2964 switch ( arch ) {
2965 case ARCH_SAMBA:
2966 strcpy(remote_arch,"Samba");
2967 break;
2968 case ARCH_WFWG:
2969 strcpy(remote_arch,"WfWg");
2970 break;
2971 case ARCH_WIN95:
2972 strcpy(remote_arch,"Win95");
2973 break;
2974 case ARCH_WINNT:
2975 strcpy(remote_arch,"WinNT");
2976 break;
2977 case ARCH_OS2:
2978 strcpy(remote_arch,"OS2");
2979 break;
2980 default:
2981 strcpy(remote_arch,"UNKNOWN");
2982 break;
2985 /* possibly reload - change of architecture */
2986 reload_services(True);
2988 /* a special case to stop password server loops */
2989 if (Index == 1 && strequal(remote_machine,myhostname) &&
2990 lp_security()==SEC_SERVER)
2991 exit_server("Password server loop!");
2993 /* Check for protocols, most desirable first */
2994 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
2996 p = smb_buf(inbuf)+1;
2997 Index = 0;
2998 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
2999 while (p < (smb_buf(inbuf) + bcc))
3001 if (strequal(p,supported_protocols[protocol].proto_name))
3002 choice = Index;
3003 Index++;
3004 p += strlen(p) + 2;
3006 if(choice != -1)
3007 break;
3010 SSVAL(outbuf,smb_vwv0,choice);
3011 if(choice != -1) {
3012 extern fstring remote_proto;
3013 strcpy(remote_proto,supported_protocols[protocol].short_name);
3014 reload_services(True);
3015 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
3016 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
3018 else {
3019 DEBUG(0,("No protocol supported !\n"));
3021 SSVAL(outbuf,smb_vwv0,choice);
3023 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3025 return(outsize);
3029 /****************************************************************************
3030 close all open files for a connection
3031 ****************************************************************************/
3032 static void close_open_files(int cnum)
3034 int i;
3035 for (i=0;i<MAX_OPEN_FILES;i++)
3036 if( Files[i].cnum == cnum && Files[i].open) {
3037 close_file(i);
3043 /****************************************************************************
3044 close a cnum
3045 ****************************************************************************/
3046 void close_cnum(int cnum, uint16 vuid)
3048 DirCacheFlush(SNUM(cnum));
3050 unbecome_user();
3052 if (!OPEN_CNUM(cnum))
3054 DEBUG(0,("Can't close cnum %d\n",cnum));
3055 return;
3058 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3059 timestring(),
3060 remote_machine,client_addr(),
3061 lp_servicename(SNUM(cnum))));
3063 yield_connection(cnum,
3064 lp_servicename(SNUM(cnum)),
3065 lp_max_connections(SNUM(cnum)));
3067 if (lp_status(SNUM(cnum)))
3068 yield_connection(cnum,"STATUS.",MAXSTATUS);
3070 close_open_files(cnum);
3071 dptr_closecnum(cnum);
3073 /* execute any "postexec = " line */
3074 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
3076 pstring cmd;
3077 strcpy(cmd,lp_postexec(SNUM(cnum)));
3078 standard_sub(cnum,cmd);
3079 smbrun(cmd,NULL,False);
3080 unbecome_user();
3083 unbecome_user();
3084 /* execute any "root postexec = " line */
3085 if (*lp_rootpostexec(SNUM(cnum)))
3087 pstring cmd;
3088 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3089 standard_sub(cnum,cmd);
3090 smbrun(cmd,NULL,False);
3093 Connections[cnum].open = False;
3094 num_connections_open--;
3095 if (Connections[cnum].ngroups && Connections[cnum].groups)
3097 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3098 free(Connections[cnum].groups);
3099 free(Connections[cnum].igroups);
3100 Connections[cnum].groups = NULL;
3101 Connections[cnum].igroups = NULL;
3102 Connections[cnum].ngroups = 0;
3105 string_set(&Connections[cnum].user,"");
3106 string_set(&Connections[cnum].dirpath,"");
3107 string_set(&Connections[cnum].connectpath,"");
3111 /****************************************************************************
3112 simple routines to do connection counting
3113 ****************************************************************************/
3114 BOOL yield_connection(int cnum,char *name,int max_connections)
3116 struct connect_record crec;
3117 pstring fname;
3118 FILE *f;
3119 int mypid = getpid();
3120 int i;
3122 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3124 if (max_connections <= 0)
3125 return(True);
3127 bzero(&crec,sizeof(crec));
3129 strcpy(fname,lp_lockdir());
3130 standard_sub(cnum,fname);
3131 trim_string(fname,"","/");
3133 strcat(fname,"/");
3134 strcat(fname,name);
3135 strcat(fname,".LCK");
3137 f = fopen(fname,"r+");
3138 if (!f)
3140 DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
3141 return(False);
3144 fseek(f,0,SEEK_SET);
3146 /* find a free spot */
3147 for (i=0;i<max_connections;i++)
3149 if (fread(&crec,sizeof(crec),1,f) != 1)
3151 DEBUG(2,("Entry not found in lock file %s\n",fname));
3152 fclose(f);
3153 return(False);
3155 if (crec.pid == mypid && crec.cnum == cnum)
3156 break;
3159 if (crec.pid != mypid || crec.cnum != cnum)
3161 fclose(f);
3162 DEBUG(2,("Entry not found in lock file %s\n",fname));
3163 return(False);
3166 bzero((void *)&crec,sizeof(crec));
3168 /* remove our mark */
3169 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3170 fwrite(&crec,sizeof(crec),1,f) != 1)
3172 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3173 fclose(f);
3174 return(False);
3177 DEBUG(3,("Yield successful\n"));
3179 fclose(f);
3180 return(True);
3184 /****************************************************************************
3185 simple routines to do connection counting
3186 ****************************************************************************/
3187 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3189 struct connect_record crec;
3190 pstring fname;
3191 FILE *f;
3192 int snum = SNUM(cnum);
3193 int i,foundi= -1;
3194 int total_recs;
3196 if (max_connections <= 0)
3197 return(True);
3199 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3201 strcpy(fname,lp_lockdir());
3202 standard_sub(cnum,fname);
3203 trim_string(fname,"","/");
3205 if (!directory_exist(fname,NULL))
3206 mkdir(fname,0755);
3208 strcat(fname,"/");
3209 strcat(fname,name);
3210 strcat(fname,".LCK");
3212 if (!file_exist(fname,NULL))
3214 int oldmask = umask(022);
3215 f = fopen(fname,"w");
3216 if (f) fclose(f);
3217 umask(oldmask);
3220 total_recs = file_size(fname) / sizeof(crec);
3222 f = fopen(fname,"r+");
3224 if (!f)
3226 DEBUG(1,("couldn't open lock file %s\n",fname));
3227 return(False);
3230 /* find a free spot */
3231 for (i=0;i<max_connections;i++)
3234 if (i>=total_recs ||
3235 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3236 fread(&crec,sizeof(crec),1,f) != 1)
3238 if (foundi < 0) foundi = i;
3239 break;
3242 if (Clear && crec.pid && !process_exists(crec.pid))
3244 fseek(f,i*sizeof(crec),SEEK_SET);
3245 bzero((void *)&crec,sizeof(crec));
3246 fwrite(&crec,sizeof(crec),1,f);
3247 if (foundi < 0) foundi = i;
3248 continue;
3250 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3252 foundi=i;
3253 if (!Clear) break;
3257 if (foundi < 0)
3259 DEBUG(3,("no free locks in %s\n",fname));
3260 fclose(f);
3261 return(False);
3264 /* fill in the crec */
3265 bzero((void *)&crec,sizeof(crec));
3266 crec.magic = 0x280267;
3267 crec.pid = getpid();
3268 crec.cnum = cnum;
3269 crec.uid = Connections[cnum].uid;
3270 crec.gid = Connections[cnum].gid;
3271 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3272 crec.start = time(NULL);
3274 StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3275 StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3277 /* make our mark */
3278 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3279 fwrite(&crec,sizeof(crec),1,f) != 1)
3281 fclose(f);
3282 return(False);
3285 fclose(f);
3286 return(True);
3289 #if DUMP_CORE
3290 /*******************************************************************
3291 prepare to dump a core file - carefully!
3292 ********************************************************************/
3293 static BOOL dump_core(void)
3295 char *p;
3296 pstring dname;
3297 strcpy(dname,debugf);
3298 if ((p=strrchr(dname,'/'))) *p=0;
3299 strcat(dname,"/corefiles");
3300 mkdir(dname,0700);
3301 sys_chown(dname,getuid(),getgid());
3302 chmod(dname,0700);
3303 if (chdir(dname)) return(False);
3304 umask(~(0700));
3306 #ifndef NO_GETRLIMIT
3307 #ifdef RLIMIT_CORE
3309 struct rlimit rlp;
3310 getrlimit(RLIMIT_CORE, &rlp);
3311 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3312 setrlimit(RLIMIT_CORE, &rlp);
3313 getrlimit(RLIMIT_CORE, &rlp);
3314 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3316 #endif
3317 #endif
3320 DEBUG(0,("Dumping core in %s\n",dname));
3321 return(True);
3323 #endif
3325 /****************************************************************************
3326 exit the server
3327 ****************************************************************************/
3328 void exit_server(char *reason)
3330 static int firsttime=1;
3331 int i;
3333 if (!firsttime) exit(0);
3334 firsttime = 0;
3336 unbecome_user();
3337 DEBUG(2,("Closing connections\n"));
3338 for (i=0;i<MAX_CONNECTIONS;i++)
3339 if (Connections[i].open)
3340 close_cnum(i,-1);
3341 #ifdef DFS_AUTH
3342 if (dcelogin_atmost_once)
3343 dfs_unlogin();
3344 #endif
3345 if (!reason) {
3346 int oldlevel = DEBUGLEVEL;
3347 DEBUGLEVEL = 10;
3348 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3349 if (last_inbuf)
3350 show_msg(last_inbuf);
3351 DEBUGLEVEL = oldlevel;
3352 DEBUG(0,("===============================================================\n"));
3353 #if DUMP_CORE
3354 if (dump_core()) return;
3355 #endif
3358 #ifdef FAST_SHARE_MODES
3359 stop_share_mode_mgmt();
3360 #endif /* FAST_SHARE_MODES */
3362 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3363 exit(0);
3366 /****************************************************************************
3367 do some standard substitutions in a string
3368 ****************************************************************************/
3369 void standard_sub(int cnum,char *s)
3371 if (!strchr(s,'%')) return;
3373 if (VALID_CNUM(cnum))
3375 string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3376 string_sub(s,"%P",Connections[cnum].connectpath);
3377 string_sub(s,"%u",Connections[cnum].user);
3378 if (strstr(s,"%H")) {
3379 char *home = get_home_dir(Connections[cnum].user);
3380 if (home) string_sub(s,"%H",home);
3382 string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3384 standard_sub_basic(s);
3388 These flags determine some of the permissions required to do an operation
3390 Note that I don't set NEED_WRITE on some write operations because they
3391 are used by some brain-dead clients when printing, and I don't want to
3392 force write permissions on print services.
3394 #define AS_USER (1<<0)
3395 #define NEED_WRITE (1<<1)
3396 #define TIME_INIT (1<<2)
3397 #define CAN_IPC (1<<3)
3398 #define AS_GUEST (1<<5)
3402 define a list of possible SMB messages and their corresponding
3403 functions. Any message that has a NULL function is unimplemented -
3404 please feel free to contribute implementations!
3406 struct smb_message_struct
3408 int code;
3409 char *name;
3410 int (*fn)();
3411 int flags;
3412 #if PROFILING
3413 unsigned long time;
3414 #endif
3416 smb_messages[] = {
3418 /* CORE PROTOCOL */
3420 {SMBnegprot,"SMBnegprot",reply_negprot,0},
3421 {SMBtcon,"SMBtcon",reply_tcon,0},
3422 {SMBtdis,"SMBtdis",reply_tdis,0},
3423 {SMBexit,"SMBexit",reply_exit,0},
3424 {SMBioctl,"SMBioctl",reply_ioctl,0},
3425 {SMBecho,"SMBecho",reply_echo,0},
3426 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3427 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3428 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3429 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3430 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3431 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3432 {SMBsearch,"SMBsearch",reply_search,AS_USER},
3433 {SMBopen,"SMBopen",reply_open,AS_USER},
3435 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3436 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3437 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
3439 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3440 {SMBread,"SMBread",reply_read,AS_USER},
3441 {SMBwrite,"SMBwrite",reply_write,AS_USER},
3442 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3443 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3444 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3445 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3446 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3448 /* this is a Pathworks specific call, allowing the
3449 changing of the root path */
3450 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
3452 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3453 {SMBflush,"SMBflush",reply_flush,AS_USER},
3454 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3455 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3456 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3457 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3458 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3459 {SMBlock,"SMBlock",reply_lock,AS_USER},
3460 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3462 /* CORE+ PROTOCOL FOLLOWS */
3464 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3465 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3466 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3467 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3468 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3470 /* LANMAN1.0 PROTOCOL FOLLOWS */
3472 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3473 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3474 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3475 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3476 {SMBwritec,"SMBwritec",NULL,AS_USER},
3477 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3478 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3479 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3480 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3481 {SMBioctls,"SMBioctls",NULL,AS_USER},
3482 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3483 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3485 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3486 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3487 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3488 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3490 {SMBffirst,"SMBffirst",reply_search,AS_USER},
3491 {SMBfunique,"SMBfunique",reply_search,AS_USER},
3492 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3494 /* LANMAN2.0 PROTOCOL FOLLOWS */
3495 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3496 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3497 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3498 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3500 /* messaging routines */
3501 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3502 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3503 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3504 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3506 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3508 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3509 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3510 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3511 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3514 /****************************************************************************
3515 return a string containing the function name of a SMB command
3516 ****************************************************************************/
3517 char *smb_fn_name(int type)
3519 static char *unknown_name = "SMBunknown";
3520 static int num_smb_messages =
3521 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3522 int match;
3524 for (match=0;match<num_smb_messages;match++)
3525 if (smb_messages[match].code == type)
3526 break;
3528 if (match == num_smb_messages)
3529 return(unknown_name);
3531 return(smb_messages[match].name);
3535 /****************************************************************************
3536 do a switch on the message type, and return the response size
3537 ****************************************************************************/
3538 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3540 static int pid= -1;
3541 int outsize = 0;
3542 static int num_smb_messages =
3543 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3544 int match;
3546 #if PROFILING
3547 struct timeval msg_start_time;
3548 struct timeval msg_end_time;
3549 static unsigned long total_time = 0;
3551 GetTimeOfDay(&msg_start_time);
3552 #endif
3554 if (pid == -1)
3555 pid = getpid();
3557 errno = 0;
3558 last_message = type;
3560 /* make sure this is an SMB packet */
3561 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3563 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3564 return(-1);
3567 for (match=0;match<num_smb_messages;match++)
3568 if (smb_messages[match].code == type)
3569 break;
3571 if (match == num_smb_messages)
3573 DEBUG(0,("Unknown message type %d!\n",type));
3574 outsize = reply_unknown(inbuf,outbuf);
3576 else
3578 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3579 if (smb_messages[match].fn)
3581 int cnum = SVAL(inbuf,smb_tid);
3582 int flags = smb_messages[match].flags;
3583 uint16 session_tag = SVAL(inbuf,smb_uid);
3585 /* does this protocol need to be run as root? */
3586 if (!(flags & AS_USER))
3587 unbecome_user();
3589 /* does this protocol need to be run as the connected user? */
3590 if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3591 if (flags & AS_GUEST)
3592 flags &= ~AS_USER;
3593 else
3594 return(ERROR(ERRSRV,ERRinvnid));
3596 /* this code is to work around a bug is MS client 3 without
3597 introducing a security hole - it needs to be able to do
3598 print queue checks as guest if it isn't logged in properly */
3599 if (flags & AS_USER)
3600 flags &= ~AS_GUEST;
3602 /* does it need write permission? */
3603 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3604 return(ERROR(ERRSRV,ERRaccess));
3606 /* ipc services are limited */
3607 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3608 return(ERROR(ERRSRV,ERRaccess));
3610 /* load service specific parameters */
3611 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3612 return(ERROR(ERRSRV,ERRaccess));
3614 /* does this protocol need to be run as guest? */
3615 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3616 return(ERROR(ERRSRV,ERRaccess));
3618 last_inbuf = inbuf;
3620 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3622 else
3624 outsize = reply_unknown(inbuf,outbuf);
3628 #if PROFILING
3629 GetTimeOfDay(&msg_end_time);
3630 if (!(smb_messages[match].flags & TIME_INIT))
3632 smb_messages[match].time = 0;
3633 smb_messages[match].flags |= TIME_INIT;
3636 unsigned long this_time =
3637 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3638 (msg_end_time.tv_usec - msg_start_time.tv_usec);
3639 smb_messages[match].time += this_time;
3640 total_time += this_time;
3642 DEBUG(2,("TIME %s %d usecs %g pct\n",
3643 smb_fn_name(type),smb_messages[match].time,
3644 (100.0*smb_messages[match].time) / total_time));
3645 #endif
3647 return(outsize);
3651 /****************************************************************************
3652 construct a chained reply and add it to the already made reply
3653 **************************************************************************/
3654 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3656 static char *orig_inbuf;
3657 static char *orig_outbuf;
3658 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3659 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3660 char *inbuf2, *outbuf2;
3661 int outsize2;
3662 char inbuf_saved[smb_wct];
3663 char outbuf_saved[smb_wct];
3664 extern int chain_size;
3665 int wct = CVAL(outbuf,smb_wct);
3666 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3668 /* maybe its not chained */
3669 if (smb_com2 == 0xFF) {
3670 CVAL(outbuf,smb_vwv0) = 0xFF;
3671 return outsize;
3674 if (chain_size == 0) {
3675 /* this is the first part of the chain */
3676 orig_inbuf = inbuf;
3677 orig_outbuf = outbuf;
3680 /* we need to tell the client where the next part of the reply will be */
3681 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3682 CVAL(outbuf,smb_vwv0) = smb_com2;
3684 /* remember how much the caller added to the chain, only counting stuff
3685 after the parameter words */
3686 chain_size += outsize - smb_wct;
3688 /* work out pointers into the original packets. The
3689 headers on these need to be filled in */
3690 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3691 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3693 /* remember the original command type */
3694 smb_com1 = CVAL(orig_inbuf,smb_com);
3696 /* save the data which will be overwritten by the new headers */
3697 memcpy(inbuf_saved,inbuf2,smb_wct);
3698 memcpy(outbuf_saved,outbuf2,smb_wct);
3700 /* give the new packet the same header as the last part of the SMB */
3701 memmove(inbuf2,inbuf,smb_wct);
3703 /* create the in buffer */
3704 CVAL(inbuf2,smb_com) = smb_com2;
3706 /* create the out buffer */
3707 bzero(outbuf2,smb_size);
3708 set_message(outbuf2,0,0,True);
3709 CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
3711 memcpy(outbuf2+4,inbuf2+4,4);
3712 CVAL(outbuf2,smb_rcls) = SUCCESS;
3713 CVAL(outbuf2,smb_reh) = 0;
3714 CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
3715 means a reply */
3716 SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
3717 SSVAL(outbuf2,smb_err,SUCCESS);
3718 SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
3719 SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
3720 SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
3721 SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
3723 DEBUG(3,("Chained message\n"));
3724 show_msg(inbuf2);
3726 /* process the request */
3727 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
3728 bufsize-chain_size);
3730 /* copy the new reply and request headers over the old ones, but
3731 preserve the smb_com field */
3732 memmove(orig_outbuf,outbuf2,smb_wct);
3733 CVAL(orig_outbuf,smb_com) = smb_com1;
3735 /* restore the saved data, being careful not to overwrite any
3736 data from the reply header */
3737 memcpy(inbuf2,inbuf_saved,smb_wct);
3739 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
3740 if (ofs < 0) ofs = 0;
3741 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
3744 return outsize2;
3749 /****************************************************************************
3750 construct a reply to the incoming packet
3751 ****************************************************************************/
3752 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3754 int type = CVAL(inbuf,smb_com);
3755 int outsize = 0;
3756 int msg_type = CVAL(inbuf,0);
3757 extern int chain_size;
3759 smb_last_time = time(NULL);
3761 chain_size = 0;
3762 chain_fnum = -1;
3764 bzero(outbuf,smb_size);
3766 if (msg_type != 0)
3767 return(reply_special(inbuf,outbuf));
3769 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3770 set_message(outbuf,0,0,True);
3772 memcpy(outbuf+4,inbuf+4,4);
3773 CVAL(outbuf,smb_rcls) = SUCCESS;
3774 CVAL(outbuf,smb_reh) = 0;
3775 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
3776 means a reply */
3777 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
3778 SSVAL(outbuf,smb_err,SUCCESS);
3779 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
3780 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
3781 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
3782 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
3784 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3786 outsize += chain_size;
3788 if(outsize > 4)
3789 smb_setlen(outbuf,outsize - 4);
3790 return(outsize);
3794 /****************************************************************************
3795 process commands from the client
3796 ****************************************************************************/
3797 static void process(void)
3799 static int trans_num = 0;
3800 int nread;
3801 extern int Client;
3803 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3804 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3805 if ((InBuffer == NULL) || (OutBuffer == NULL))
3806 return;
3808 InBuffer += SMB_ALIGNMENT;
3809 OutBuffer += SMB_ALIGNMENT;
3811 #if PRIME_NMBD
3812 DEBUG(3,("priming nmbd\n"));
3814 struct in_addr ip;
3815 ip = *interpret_addr2("localhost");
3816 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3817 *OutBuffer = 0;
3818 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
3820 #endif
3822 while (True)
3824 int32 len;
3825 int msg_type;
3826 int msg_flags;
3827 int type;
3828 int deadtime = lp_deadtime()*60;
3829 int counter;
3830 int last_keepalive=0;
3832 if (deadtime <= 0)
3833 deadtime = DEFAULT_SMBD_TIMEOUT;
3835 if (lp_readprediction())
3836 do_read_prediction();
3838 errno = 0;
3840 for (counter=SMBD_SELECT_LOOP;
3841 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3842 counter += SMBD_SELECT_LOOP)
3844 int i;
3845 time_t t;
3846 BOOL allidle = True;
3847 extern int keepalive;
3849 if (smb_read_error == READ_EOF) {
3850 DEBUG(3,("end of file from client\n"));
3851 return;
3854 if (smb_read_error == READ_ERROR) {
3855 DEBUG(3,("receive_smb error (%s) exiting\n",
3856 strerror(errno)));
3857 return;
3860 t = time(NULL);
3862 /* become root again if waiting */
3863 unbecome_user();
3865 /* check for smb.conf reload */
3866 if (!(counter%SMBD_RELOAD_CHECK))
3867 reload_services(True);
3869 #if 0 /* JRA */
3870 /* check the share modes every 10 secs */
3871 if (!(counter%SHARE_MODES_CHECK))
3872 check_share_modes();
3874 /* clean the share modes every 5 minutes */
3875 if (!(counter%SHARE_MODES_CLEAN))
3876 clean_share_modes();
3877 #endif /* JRA */
3879 /* automatic timeout if all connections are closed */
3880 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
3881 DEBUG(2,("%s Closing idle connection\n",timestring()));
3882 return;
3885 if (keepalive && (counter-last_keepalive)>keepalive) {
3886 extern int password_client;
3887 if (!send_keepalive(Client)) {
3888 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3889 return;
3891 /* also send a keepalive to the password server if its still
3892 connected */
3893 if (password_client != -1)
3894 send_keepalive(password_client);
3895 last_keepalive = counter;
3898 /* check for connection timeouts */
3899 for (i=0;i<MAX_CONNECTIONS;i++)
3900 if (Connections[i].open)
3902 /* close dirptrs on connections that are idle */
3903 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
3904 dptr_idlecnum(i);
3906 if (Connections[i].num_files_open > 0 ||
3907 (t-Connections[i].lastused)<deadtime)
3908 allidle = False;
3911 if (allidle && num_connections_open>0) {
3912 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3913 return;
3917 msg_type = CVAL(InBuffer,0);
3918 msg_flags = CVAL(InBuffer,1);
3919 type = CVAL(InBuffer,smb_com);
3921 len = smb_len(InBuffer);
3923 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
3925 nread = len + 4;
3927 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
3929 #ifdef WITH_VTP
3930 if(trans_num == 1 && VT_Check(InBuffer)) {
3931 VT_Process();
3932 return;
3934 #endif
3937 if (msg_type == 0)
3938 show_msg(InBuffer);
3940 nread = construct_reply(InBuffer,OutBuffer,nread,max_send);
3942 if(nread > 0) {
3943 if (CVAL(OutBuffer,0) == 0)
3944 show_msg(OutBuffer);
3946 if (nread != smb_len(OutBuffer) + 4)
3948 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3949 nread,
3950 smb_len(OutBuffer)));
3952 else
3953 send_smb(Client,OutBuffer);
3955 trans_num++;
3960 /****************************************************************************
3961 initialise connect, service and file structs
3962 ****************************************************************************/
3963 static void init_structs(void )
3965 int i;
3966 get_myname(myhostname,NULL);
3968 for (i=0;i<MAX_CONNECTIONS;i++)
3970 Connections[i].open = False;
3971 Connections[i].num_files_open=0;
3972 Connections[i].lastused=0;
3973 Connections[i].used=False;
3974 string_init(&Connections[i].user,"");
3975 string_init(&Connections[i].dirpath,"");
3976 string_init(&Connections[i].connectpath,"");
3977 string_init(&Connections[i].origpath,"");
3980 for (i=0;i<MAX_OPEN_FILES;i++)
3982 Files[i].open = False;
3983 string_init(&Files[i].name,"");
3987 for (i=0;i<MAX_OPEN_FILES;i++)
3989 file_fd_struct *fd_ptr = &FileFd[i];
3990 fd_ptr->ref_count = 0;
3991 fd_ptr->dev = (int32)-1;
3992 fd_ptr->inode = (int32)-1;
3993 fd_ptr->fd = -1;
3994 fd_ptr->fd_readonly = -1;
3995 fd_ptr->fd_writeonly = -1;
3996 fd_ptr->real_open_flags = -1;
3999 init_dptrs();
4002 /****************************************************************************
4003 usage on the program
4004 ****************************************************************************/
4005 static void usage(char *pname)
4007 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4009 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
4010 printf("Version %s\n",VERSION);
4011 printf("\t-D become a daemon\n");
4012 printf("\t-p port listen on the specified port\n");
4013 printf("\t-d debuglevel set the debuglevel\n");
4014 printf("\t-l log basename. Basename for log/debug files\n");
4015 printf("\t-s services file. Filename of services file\n");
4016 printf("\t-P passive only\n");
4017 printf("\t-a overwrite log file, don't append\n");
4018 printf("\n");
4022 /****************************************************************************
4023 main program
4024 ****************************************************************************/
4025 int main(int argc,char *argv[])
4027 extern BOOL append_log;
4028 /* shall I run as a daemon */
4029 BOOL is_daemon = False;
4030 int port = SMB_PORT;
4031 int opt;
4032 extern char *optarg;
4033 char pidFile[100] = { 0 };
4035 #ifdef NEED_AUTH_PARAMETERS
4036 set_auth_parameters(argc,argv);
4037 #endif
4039 #ifdef SecureWare
4040 setluid(0);
4041 #endif
4043 append_log = True;
4045 TimeInit();
4047 strcpy(debugf,SMBLOGFILE);
4049 setup_logging(argv[0],False);
4051 charset_initialise(-1);
4053 /* make absolutely sure we run as root - to handle cases whre people
4054 are crazy enough to have it setuid */
4055 #ifdef USE_SETRES
4056 setresuid(0,0,0);
4057 #else
4058 setuid(0);
4059 seteuid(0);
4060 setuid(0);
4061 seteuid(0);
4062 #endif
4064 fault_setup(exit_server);
4065 signal(SIGTERM , SIGNAL_CAST dflt_sig);
4067 /* we want total control over the permissions on created files,
4068 so set our umask to 0 */
4069 umask(0);
4071 GetWd(OriginalDir);
4073 init_uid();
4075 /* this is for people who can't start the program correctly */
4076 while (argc > 1 && (*argv[1] != '-'))
4078 argv++;
4079 argc--;
4082 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
4083 switch (opt)
4085 case 'f':
4086 strncpy(pidFile, optarg, sizeof(pidFile));
4087 break;
4088 case 'O':
4089 strcpy(user_socket_options,optarg);
4090 break;
4091 case 'i':
4092 strcpy(scope,optarg);
4093 break;
4094 case 'P':
4096 extern BOOL passive;
4097 passive = True;
4099 break;
4100 case 's':
4101 strcpy(servicesf,optarg);
4102 break;
4103 case 'l':
4104 strcpy(debugf,optarg);
4105 break;
4106 case 'a':
4108 extern BOOL append_log;
4109 append_log = !append_log;
4111 break;
4112 case 'D':
4113 is_daemon = True;
4114 break;
4115 case 'd':
4116 if (*optarg == 'A')
4117 DEBUGLEVEL = 10000;
4118 else
4119 DEBUGLEVEL = atoi(optarg);
4120 break;
4121 case 'p':
4122 port = atoi(optarg);
4123 break;
4124 case 'h':
4125 usage(argv[0]);
4126 exit(0);
4127 break;
4128 default:
4129 usage(argv[0]);
4130 exit(1);
4133 reopen_logs();
4135 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4136 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4138 #ifndef NO_GETRLIMIT
4139 #ifdef RLIMIT_NOFILE
4141 struct rlimit rlp;
4142 getrlimit(RLIMIT_NOFILE, &rlp);
4143 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4144 setrlimit(RLIMIT_NOFILE, &rlp);
4145 getrlimit(RLIMIT_NOFILE, &rlp);
4146 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4148 #endif
4149 #endif
4152 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4153 getuid(),getgid(),geteuid(),getegid()));
4155 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4157 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4158 exit(1);
4161 init_structs();
4163 if (!reload_services(False))
4164 return(-1);
4166 charset_initialise(lp_client_code_page());
4168 strcpy(myworkgroup, lp_workgroup());
4170 #ifndef NO_SIGNAL_TEST
4171 signal(SIGHUP,SIGNAL_CAST sig_hup);
4172 #endif
4174 DEBUG(3,("%s loaded services\n",timestring()));
4176 if (!is_daemon && !is_a_socket(0))
4178 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4179 is_daemon = True;
4182 if (is_daemon)
4184 DEBUG(3,("%s becoming a daemon\n",timestring()));
4185 become_daemon();
4188 if (*pidFile)
4190 int fd;
4191 char buf[20];
4193 if ((fd = open(pidFile,
4194 O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4196 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4197 exit(1);
4199 if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4201 DEBUG(0,("ERROR: smbd is already running\n"));
4202 exit(1);
4204 sprintf(buf, "%u\n", (unsigned int) getpid());
4205 if (write(fd, buf, strlen(buf)) < 0)
4207 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4208 exit(1);
4210 /* Leave pid file open & locked for the duration... */
4213 if (!open_sockets(is_daemon,port))
4214 exit(1);
4216 #ifdef FAST_SHARE_MODES
4217 if (!start_share_mode_mgmt())
4218 exit(1);
4219 #endif /* FAST_SHARE_MODES */
4221 /* possibly reload the services file. */
4222 reload_services(True);
4224 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
4226 if (*lp_rootdir())
4228 if (sys_chroot(lp_rootdir()) == 0)
4229 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4232 process();
4233 close_sockets();
4235 exit_server("normal exit");
4236 return(0);