2 Unix SMB/Netbios implementation.
4 Main SMB server routines
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 pstring servicesf
= CONFIGFILE
;
26 extern pstring debugf
;
27 extern pstring sesssetup_user
;
29 char *InBuffer
= NULL
;
30 char *OutBuffer
= NULL
;
31 char *last_inbuf
= NULL
;
36 BOOL share_mode_pending
= False
;
38 /* the last message the was processed */
39 int last_message
= -1;
41 /* a useful macro to debug the last message processed */
42 #define LAST_MESSAGE() smb_fn_name(last_message)
45 extern int DEBUGLEVEL
;
46 extern int case_default
;
47 extern BOOL case_sensitive
;
48 extern BOOL case_preserve
;
49 extern BOOL use_mangled_map
;
50 extern BOOL short_case_preserve
;
51 extern BOOL case_mangle
;
52 extern time_t smb_last_time
;
54 extern int smb_read_error
;
56 extern pstring user_socket_options
;
58 connection_struct Connections
[MAX_CONNECTIONS
];
59 files_struct Files
[MAX_OPEN_FILES
];
62 * Indirection for file fd's. Needed as POSIX locking
63 * is based on file/process, not fd/process.
65 file_fd_struct FileFd
[MAX_OPEN_FILES
];
66 int max_file_fd_used
= 0;
70 int maxxmit
= BUFFER_SIZE
;
72 /* a fnum to use when chaining */
75 /* number of open connections */
76 static int num_connections_open
= 0;
78 extern fstring remote_machine
;
82 /* these can be set by some functions to override the error codes */
83 int unix_ERR_class
=SUCCESS
;
87 extern int extra_time_offset
;
89 extern pstring myhostname
;
91 static int find_free_connection(int hash
);
93 /* for readability... */
94 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
95 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
96 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
97 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
98 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
100 /****************************************************************************
101 when exiting, take the whole family
102 ****************************************************************************/
105 exit_server("caught signal");
107 /****************************************************************************
108 Send a SIGTERM to our process group.
109 *****************************************************************************/
112 if(am_parent
) kill(0,SIGTERM
);
115 /****************************************************************************
116 change a dos mode to a unix mode
117 base permission for files:
118 everybody gets read bit set
119 dos readonly is represented in unix by removing everyone's write bit
120 dos archive is represented in unix by the user's execute bit
121 dos system is represented in unix by the group's execute bit
122 dos hidden is represented in unix by the other's execute bit
123 base permission for directories:
124 dos directory is represented in unix by unix's dir bit and the exec bit
125 ****************************************************************************/
126 mode_t
unix_mode(int cnum
,int dosmode
)
128 mode_t result
= (S_IRUSR
| S_IRGRP
| S_IROTH
);
130 if ( !IS_DOS_READONLY(dosmode
) )
131 result
|= (S_IWUSR
| S_IWGRP
| S_IWOTH
);
133 if (IS_DOS_DIR(dosmode
)) {
134 result
|= (S_IFDIR
| S_IXUSR
| S_IXGRP
| S_IXOTH
| S_IWUSR
);
135 result
&= (lp_dir_mode(SNUM(cnum
)) | 0700);
137 if (MAP_ARCHIVE(cnum
) && IS_DOS_ARCHIVE(dosmode
))
140 if (MAP_SYSTEM(cnum
) && IS_DOS_SYSTEM(dosmode
))
143 if (MAP_HIDDEN(cnum
) && IS_DOS_HIDDEN(dosmode
))
146 result
&= CREATE_MODE(cnum
);
152 /****************************************************************************
153 change a unix mode to a dos mode
154 ****************************************************************************/
155 int dos_mode(int cnum
,char *path
,struct stat
*sbuf
)
158 extern struct current_user current_user
;
160 if (CAN_WRITE(cnum
) && !lp_alternate_permissions(SNUM(cnum
))) {
161 if (!((sbuf
->st_mode
& S_IWOTH
) ||
162 Connections
[cnum
].admin_user
||
163 ((sbuf
->st_mode
& S_IWUSR
) && current_user
.uid
==sbuf
->st_uid
) ||
164 ((sbuf
->st_mode
& S_IWGRP
) &&
165 in_group(sbuf
->st_gid
,current_user
.gid
,
166 current_user
.ngroups
,current_user
.igroups
))))
169 if ((sbuf
->st_mode
& S_IWUSR
) == 0)
173 if ((sbuf
->st_mode
& S_IXUSR
) != 0)
176 if (MAP_SYSTEM(cnum
) && ((sbuf
->st_mode
& S_IXGRP
) != 0))
179 if (MAP_HIDDEN(cnum
) && ((sbuf
->st_mode
& S_IXOTH
) != 0))
182 if (S_ISDIR(sbuf
->st_mode
))
183 result
= aDIR
| (result
& aRONLY
);
186 if (S_ISLNK(sbuf
->st_mode
) && S_ISDIR(sbuf
->st_mode
))
190 /* hide files with a name starting with a . */
191 if (lp_hide_dot_files(SNUM(cnum
)))
193 char *p
= strrchr(path
,'/');
199 if (p
[0] == '.' && p
[1] != '.' && p
[1] != 0)
207 /*******************************************************************
208 chmod a file - but preserve some bits
209 ********************************************************************/
210 int dos_chmod(int cnum
,char *fname
,int dosmode
,struct stat
*st
)
219 if (sys_stat(fname
,st
)) return(-1);
222 if (S_ISDIR(st
->st_mode
)) dosmode
|= aDIR
;
224 if (dos_mode(cnum
,fname
,st
) == dosmode
) return(0);
226 unixmode
= unix_mode(cnum
,dosmode
);
228 /* preserve the s bits */
229 mask
|= (S_ISUID
| S_ISGID
);
231 /* preserve the t bit */
236 /* possibly preserve the x bits */
237 if (!MAP_ARCHIVE(cnum
)) mask
|= S_IXUSR
;
238 if (!MAP_SYSTEM(cnum
)) mask
|= S_IXGRP
;
239 if (!MAP_HIDDEN(cnum
)) mask
|= S_IXOTH
;
241 unixmode
|= (st
->st_mode
& mask
);
243 /* if we previously had any r bits set then leave them alone */
244 if ((tmp
= st
->st_mode
& (S_IRUSR
|S_IRGRP
|S_IROTH
))) {
245 unixmode
&= ~(S_IRUSR
|S_IRGRP
|S_IROTH
);
249 /* if we previously had any w bits set then leave them alone
250 if the new mode is not rdonly */
251 if (!IS_DOS_READONLY(dosmode
) &&
252 (tmp
= st
->st_mode
& (S_IWUSR
|S_IWGRP
|S_IWOTH
))) {
253 unixmode
&= ~(S_IWUSR
|S_IWGRP
|S_IWOTH
);
257 return(sys_chmod(fname
,unixmode
));
261 /****************************************************************************
262 check if two filenames are equal
264 this needs to be careful about whether we are case sensitive
265 ****************************************************************************/
266 static BOOL
fname_equal(char *name1
, char *name2
)
268 int l1
= strlen(name1
);
269 int l2
= strlen(name2
);
271 /* handle filenames ending in a single dot */
272 if (l1
-l2
== 1 && name1
[l1
-1] == '.' && lp_strip_dot())
276 ret
= fname_equal(name1
,name2
);
281 if (l2
-l1
== 1 && name2
[l2
-1] == '.' && lp_strip_dot())
285 ret
= fname_equal(name1
,name2
);
290 /* now normal filename handling */
292 return(strcmp(name1
,name2
) == 0);
294 return(strequal(name1
,name2
));
298 /****************************************************************************
299 mangle the 2nd name and check if it is then equal to the first name
300 ****************************************************************************/
301 static BOOL
mangled_equal(char *name1
, char *name2
)
305 if (is_8_3(name2
, True
))
308 strcpy(tmpname
,name2
);
309 mangle_name_83(tmpname
);
311 return(strequal(name1
,tmpname
));
315 /****************************************************************************
316 scan a directory to find a filename, matching without case sensitivity
318 If the name looks like a mangled name then try via the mangling functions
319 ****************************************************************************/
320 static BOOL
scan_directory(char *path
, char *name
,int snum
,BOOL docache
)
327 mangled
= is_mangled(name
);
329 /* handle null paths */
333 if (docache
&& (dname
= DirCacheCheck(path
,name
,snum
))) {
339 check_mangled_stack(name
);
341 /* open the directory */
342 if (!(cur_dir
= OpenDir(path
)))
344 DEBUG(3,("scan dir didn't open dir [%s]\n",path
));
348 /* now scan for matching names */
349 while ((dname
= ReadDirName(cur_dir
)))
352 (strequal(dname
,".") || strequal(dname
,"..")))
356 if (!name_map_mangle(name2
,False
,snum
)) continue;
358 if ((mangled
&& mangled_equal(name
,name2
))
359 || fname_equal(name
, name2
))
361 /* we've found the file, change it's name and return */
362 if (docache
) DirCacheAdd(path
,name
,dname
,snum
);
373 /****************************************************************************
374 This routine is called to convert names from the dos namespace to unix
375 namespace. It needs to handle any case conversions, mangling, format
378 We assume that we have already done a chdir() to the right "root" directory
381 The function will return False if some part of the name except for the last
382 part cannot be resolved
384 If the saved_last_component != 0, then the unmodified last component
385 of the pathname is returned there. This is used in an exceptional
386 case in reply_mv (so far). If saved_last_component == 0 then nothing
388 ****************************************************************************/
389 BOOL
unix_convert(char *name
,int cnum
,pstring saved_last_component
)
396 if(saved_last_component
)
397 *saved_last_component
= 0;
399 /* convert to basic unix format - removing \ chars and cleaning it up */
401 unix_clean_name(name
);
403 /* names must be relative to the root of the service - trim any leading /.
404 also trim trailing /'s */
405 trim_string(name
,"/","/");
408 * Ensure saved_last_component is valid even if file exists.
410 if(saved_last_component
) {
411 end
= strrchr(name
, '/');
413 strcpy(saved_last_component
, end
+ 1);
415 strcpy(saved_last_component
, name
);
418 if (!case_sensitive
&&
419 (!case_preserve
|| (is_8_3(name
, False
) && !short_case_preserve
)))
422 /* check if it's a printer file */
423 if (Connections
[cnum
].printer
)
425 if ((! *name
) || strchr(name
,'/') || !is_8_3(name
, True
))
429 sprintf(name2
,"%.6s.XXXXXX",remote_machine
);
430 /* sanitise the name */
431 for (s
=name2
; *s
; s
++)
432 if (!issafe(*s
)) *s
= '_';
433 strcpy(name
,(char *)mktemp(name2
));
438 /* stat the name - if it exists then we are all done! */
439 if (sys_stat(name
,&st
) == 0)
442 DEBUG(5,("unix_convert(%s,%d)\n",name
,cnum
));
444 /* a special case - if we don't have any mangling chars and are case
445 sensitive then searching won't help */
446 if (case_sensitive
&& !is_mangled(name
) &&
447 !lp_strip_dot() && !use_mangled_map
)
450 /* now we need to recursively match the name against the real
451 directory structure */
454 while (strncmp(start
,"./",2) == 0)
457 /* now match each part of the path name separately, trying the names
458 as is first, then trying to scan the directory for matching names */
459 for (;start
;start
= (end
?end
+1:(char *)NULL
))
461 /* pinpoint the end of this section of the filename */
462 end
= strchr(start
, '/');
464 /* chop the name at this point */
467 if(saved_last_component
!= 0)
468 strcpy(saved_last_component
, end
? end
+ 1 : start
);
470 /* check if the name exists up to this point */
471 if (sys_stat(name
, &st
) == 0)
473 /* it exists. it must either be a directory or this must be
474 the last part of the path for it to be OK */
475 if (end
&& !(st
.st_mode
& S_IFDIR
))
477 /* an intermediate part of the name isn't a directory */
478 DEBUG(5,("Not a dir %s\n",start
));
489 /* remember the rest of the pathname so it can be restored
491 if (end
) strcpy(rest
,end
+1);
493 /* try to find this part of the path in the directory */
494 if (strchr(start
,'?') || strchr(start
,'*') ||
495 !scan_directory(dirpath
, start
, SNUM(cnum
), end
?True
:False
))
499 /* an intermediate part of the name can't be found */
500 DEBUG(5,("Intermediate not found %s\n",start
));
505 /* just the last part of the name doesn't exist */
506 /* we may need to strupper() or strlower() it in case
507 this conversion is being used for file creation
509 /* if the filename is of mixed case then don't normalise it */
510 if (!case_preserve
&&
511 (!strhasupper(start
) || !strhaslower(start
)))
514 /* check on the mangled stack to see if we can recover the
515 base of the filename */
516 if (is_mangled(start
))
517 check_mangled_stack(start
);
519 DEBUG(5,("New file %s\n",start
));
523 /* restore the rest of the string */
526 strcpy(start
+strlen(start
)+1,rest
);
527 end
= start
+ strlen(start
);
531 /* add to the dirpath that we have resolved so far */
532 if (*dirpath
) strcat(dirpath
,"/");
533 strcat(dirpath
,start
);
535 /* restore the / that we wiped out earlier */
539 /* the name has been resolved */
540 DEBUG(5,("conversion finished %s\n",name
));
545 /****************************************************************************
546 normalise for DOS usage
547 ****************************************************************************/
548 static void disk_norm(int *bsize
,int *dfree
,int *dsize
)
550 /* check if the disk is beyond the max disk size */
551 int maxdisksize
= lp_maxdisksize();
553 /* convert to blocks - and don't overflow */
554 maxdisksize
= ((maxdisksize
*1024)/(*bsize
))*1024;
555 if (*dsize
> maxdisksize
) *dsize
= maxdisksize
;
556 if (*dfree
> maxdisksize
) *dfree
= maxdisksize
-1; /* the -1 should stop
561 while (*dfree
> WORDMAX
|| *dsize
> WORDMAX
|| *bsize
< 512)
566 if (*bsize
> WORDMAX
)
569 if (*dsize
> WORDMAX
)
571 if (*dfree
> WORDMAX
)
578 /****************************************************************************
579 return number of 1K blocks available on a path and total number
580 ****************************************************************************/
581 int disk_free(char *path
,int *bsize
,int *dfree
,int *dsize
)
583 char *df_command
= lp_dfree_command();
597 if (disk_quotas(path
, bsize
, dfree
, dsize
))
599 disk_norm(bsize
,dfree
,dsize
);
600 return(((*bsize
)/1024)*(*dfree
));
605 /* possibly use system() to get the result */
606 if (df_command
&& *df_command
)
612 sprintf(outfile
,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
613 sprintf(syscmd
,"%s %s",df_command
,path
);
614 standard_sub_basic(syscmd
);
616 ret
= smbrun(syscmd
,outfile
,False
);
617 DEBUG(3,("Running the command `%s' gave %d\n",syscmd
,ret
));
620 FILE *f
= fopen(outfile
,"r");
626 fscanf(f
,"%d %d %d",dsize
,dfree
,bsize
);
630 DEBUG(0,("Can't open %s\n",outfile
));
634 disk_norm(bsize
,dfree
,dsize
);
635 return(((*bsize
)/1024)*(*dfree
));
639 DEBUG(1,("Warning - no statfs function\n"));
643 if (statfs(path
,&fs
,sizeof(fs
),0) != 0)
646 if (statvfs(path
, &fs
))
649 if (statfs(path
,&fs
,sizeof(fs
)) == -1)
651 if (statfs(path
,&fs
) == -1)
653 #endif /* USE_STATVFS */
656 DEBUG(3,("dfree call failed code errno=%d\n",errno
));
660 return(((*bsize
)/1024)*(*dfree
));
665 *dfree
= fs
.fd_req
.bfree
;
666 *dsize
= fs
.fd_req
.btot
;
669 *bsize
= fs
.f_frsize
;
672 /* eg: osf1 has f_fsize = fundamental filesystem block size,
673 f_bsize = optimal transfer block size (MX: 94-04-19) */
678 #endif /* USE_STATVFS */
683 *dfree
= fs
.f_bavail
;
685 *dsize
= fs
.f_blocks
;
688 #if defined(SCO) || defined(ISC) || defined(MIPS)
692 /* handle rediculous bsize values - some OSes are broken */
693 if ((*bsize
) < 512 || (*bsize
)>0xFFFF) *bsize
= 1024;
695 disk_norm(bsize
,dfree
,dsize
);
701 DEBUG(0,("dfree seems to be broken on your system\n"));
702 *dsize
= 20*1024*1024/(*bsize
);
703 *dfree
= MAX(1,*dfree
);
705 return(((*bsize
)/1024)*(*dfree
));
710 /****************************************************************************
711 wrap it to get filenames right
712 ****************************************************************************/
713 int sys_disk_free(char *path
,int *bsize
,int *dfree
,int *dsize
)
715 return(disk_free(dos_to_unix(path
,False
),bsize
,dfree
,dsize
));
720 /****************************************************************************
721 check a filename - possibly caling reducename
723 This is called by every routine before it allows an operation on a filename.
724 It does any final confirmation necessary to ensure that the filename is
725 a valid one for the user to access.
726 ****************************************************************************/
727 BOOL
check_name(char *name
,int cnum
)
733 if( is_vetoed_path(name
))
735 DEBUG(5,("file path name %s vetoed\n",name
));
739 ret
= reduce_name(name
,Connections
[cnum
].connectpath
,lp_widelinks(SNUM(cnum
)));
741 DEBUG(5,("check_name on %s failed\n",name
));
746 /****************************************************************************
747 check a filename - possibly caling reducename
748 ****************************************************************************/
749 static void check_for_pipe(char *fname
)
751 /* special case of pipe opens */
755 if (strstr(s
,"pipe/"))
757 DEBUG(3,("Rejecting named pipe open for %s\n",fname
));
758 unix_ERR_class
= ERRSRV
;
759 unix_ERR_code
= ERRaccess
;
763 /****************************************************************************
764 fd support routines - attempt to do a sys_open
765 ****************************************************************************/
767 int fd_attempt_open(char *fname
, int flags
, int mode
)
769 int fd
= sys_open(fname
,flags
,mode
);
771 /* Fix for files ending in '.' */
772 if((fd
== -1) && (errno
== ENOENT
) &&
773 (strchr(fname
,'.')==NULL
))
776 fd
= sys_open(fname
,flags
,mode
);
779 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
780 if ((fd
== -1) && (errno
== ENAMETOOLONG
))
783 char *p
= strrchr(fname
, '/');
785 if (p
== fname
) /* name is "/xxx" */
787 max_len
= pathconf("/", _PC_NAME_MAX
);
790 else if ((p
== NULL
) || (p
== fname
))
793 max_len
= pathconf(".", _PC_NAME_MAX
);
798 max_len
= pathconf(fname
, _PC_NAME_MAX
);
802 if (strlen(p
) > max_len
)
804 char tmp
= p
[max_len
];
807 if ((fd
= sys_open(fname
,flags
,mode
)) == -1)
815 /****************************************************************************
816 fd support routines - attempt to find an already open file by dev
817 and inode - increments the ref_count of the returned file_fd_struct *.
818 ****************************************************************************/
819 file_fd_struct
*fd_get_already_open(struct stat
*sbuf
)
822 file_fd_struct
*fd_ptr
;
827 for(i
= 0; i
<= max_file_fd_used
; i
++) {
829 if((fd_ptr
->ref_count
> 0) &&
830 (((int32
)sbuf
->st_dev
) == fd_ptr
->dev
) &&
831 (((int32
)sbuf
->st_ino
) == fd_ptr
->inode
)) {
834 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
835 i
, fd_ptr
->dev
, fd_ptr
->inode
, fd_ptr
->ref_count
));
842 /****************************************************************************
843 fd support routines - attempt to find a empty slot in the FileFd array.
844 Increments the ref_count of the returned entry.
845 ****************************************************************************/
846 file_fd_struct
*fd_get_new()
849 file_fd_struct
*fd_ptr
;
851 for(i
= 0; i
< MAX_OPEN_FILES
; i
++) {
853 if(fd_ptr
->ref_count
== 0) {
854 fd_ptr
->dev
= (int32
)-1;
855 fd_ptr
->inode
= (int32
)-1;
857 fd_ptr
->fd_readonly
= -1;
858 fd_ptr
->fd_writeonly
= -1;
859 fd_ptr
->real_open_flags
= -1;
861 /* Increment max used counter if neccessary, cuts down
862 on search time when re-using */
863 if(i
> max_file_fd_used
)
864 max_file_fd_used
= i
;
865 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
866 i
, fd_ptr
->dev
, fd_ptr
->inode
));
870 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
875 /****************************************************************************
876 fd support routines - attempt to re-open an already open fd as O_RDWR.
877 Save the already open fd (we cannot close due to POSIX file locking braindamage.
878 ****************************************************************************/
880 void fd_attempt_reopen(char *fname
, int mode
, file_fd_struct
*fd_ptr
)
882 int fd
= sys_open( fname
, O_RDWR
, mode
);
887 if(fd_ptr
->real_open_flags
== O_RDONLY
)
888 fd_ptr
->fd_readonly
= fd_ptr
->fd
;
889 if(fd_ptr
->real_open_flags
== O_WRONLY
)
890 fd_ptr
->fd_writeonly
= fd_ptr
->fd
;
893 fd_ptr
->real_open_flags
= O_RDWR
;
896 /****************************************************************************
897 fd support routines - attempt to close the file referenced by this fd.
898 Decrements the ref_count and returns it.
899 ****************************************************************************/
900 int fd_attempt_close(file_fd_struct
*fd_ptr
)
902 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
904 fd_ptr
->fd
, fd_ptr
->dev
, fd_ptr
->inode
,
905 fd_ptr
->real_open_flags
,
907 if(fd_ptr
->ref_count
> 0) {
909 if(fd_ptr
->ref_count
== 0) {
912 if(fd_ptr
->fd_readonly
!= -1)
913 close(fd_ptr
->fd_readonly
);
914 if(fd_ptr
->fd_writeonly
!= -1)
915 close(fd_ptr
->fd_writeonly
);
917 fd_ptr
->fd_readonly
= -1;
918 fd_ptr
->fd_writeonly
= -1;
919 fd_ptr
->real_open_flags
= -1;
924 return fd_ptr
->ref_count
;
927 /****************************************************************************
929 ****************************************************************************/
930 void open_file(int fnum
,int cnum
,char *fname1
,int flags
,int mode
, struct stat
*sbuf
)
932 extern struct current_user current_user
;
935 file_fd_struct
*fd_ptr
;
937 Files
[fnum
].open
= False
;
938 Files
[fnum
].fd_ptr
= 0;
941 strcpy(fname
,fname1
);
943 /* check permissions */
944 if ((flags
!= O_RDONLY
) && !CAN_WRITE(cnum
) && !Connections
[cnum
].printer
)
946 DEBUG(3,("Permission denied opening %s\n",fname
));
947 check_for_pipe(fname
);
951 /* this handles a bug in Win95 - it doesn't say to create the file when it
953 if (Connections
[cnum
].printer
)
957 if (flags == O_WRONLY)
958 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
962 /* XXXX - is this OK?? */
963 /* this works around a utime bug but can cause other problems */
964 if ((flags
& (O_WRONLY
|O_RDWR
)) && (flags
& O_CREAT
) && !(flags
& O_APPEND
))
969 * Ensure we have a valid struct stat so we can search the
973 if(stat(fname
, &statbuf
) < 0) {
974 if(errno
!= ENOENT
) {
975 DEBUG(3,("Error doing stat on file %s (%s)\n",
976 fname
,strerror(errno
)));
978 check_for_pipe(fname
);
988 * Check to see if we have this file already
989 * open. If we do, just use the already open fd and increment the
990 * reference count (fd_get_already_open increments the ref_count).
992 if((fd_ptr
= fd_get_already_open(sbuf
))!= 0) {
994 int accmode
= (flags
& (O_RDONLY
| O_WRONLY
| O_RDWR
));
996 /* File was already open. */
997 if((flags
& O_CREAT
) && (flags
& O_EXCL
)) {
1004 * If not opened O_RDWR try
1005 * and do that here - a chmod may have been done
1006 * between the last open and now.
1008 if(fd_ptr
->real_open_flags
!= O_RDWR
)
1009 fd_attempt_reopen(fname
, mode
, fd_ptr
);
1012 * Ensure that if we wanted write access
1013 * it has been opened for write, and if we wanted read it
1014 * was open for read.
1016 if(((accmode
== O_WRONLY
) && (fd_ptr
->real_open_flags
== O_RDONLY
)) ||
1017 ((accmode
== O_RDONLY
) && (fd_ptr
->real_open_flags
== O_WRONLY
)) ||
1018 ((accmode
== O_RDWR
) && (fd_ptr
->real_open_flags
!= O_RDWR
))) {
1019 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1020 fd_ptr
->real_open_flags
, fname
,strerror(EACCES
),flags
));
1021 check_for_pipe(fname
);
1022 fd_ptr
->ref_count
--;
1027 * If O_TRUNC was set, ensure we truncate the file.
1028 * open_file_shared explicitly clears this flag before
1029 * calling open_file, so we can safely do this here.
1032 ftruncate(fd_ptr
->fd
, 0);
1036 /* We need to allocate a new file_fd_struct (this increments the
1038 if((fd_ptr
= fd_get_new()) == 0)
1041 * Whatever the requested flags, attempt read/write access,
1042 * as we don't know what flags future file opens may require.
1043 * If this fails, try again with the required flags.
1044 * Even if we open read/write when only read access was
1045 * requested the setting of the can_write flag in
1046 * the file_struct will protect us from errant
1047 * write requests. We never need to worry about O_APPEND
1048 * as this is not set anywhere in Samba.
1050 fd_ptr
->real_open_flags
= O_RDWR
;
1051 /* Set the flags as needed without the read/write modes. */
1052 open_flags
= flags
& ~(O_RDWR
|O_WRONLY
|O_RDONLY
);
1053 fd_ptr
->fd
= fd_attempt_open(fname
, open_flags
|O_RDWR
, mode
);
1055 * On some systems opening a file for R/W access on a read only
1056 * filesystems sets errno to EROFS.
1059 if((fd_ptr
->fd
== -1) && ((errno
== EACCES
) || (errno
== EROFS
))) {
1060 #else /* No EROFS */
1061 if((fd_ptr
->fd
== -1) && (errno
== EACCES
)) {
1063 if(flags
& O_WRONLY
) {
1064 fd_ptr
->fd
= fd_attempt_open(fname
, open_flags
|O_WRONLY
, mode
);
1065 fd_ptr
->real_open_flags
= O_WRONLY
;
1067 fd_ptr
->fd
= fd_attempt_open(fname
, open_flags
|O_RDONLY
, mode
);
1068 fd_ptr
->real_open_flags
= O_RDONLY
;
1073 if ((fd_ptr
->fd
>=0) &&
1074 Connections
[cnum
].printer
&& lp_minprintspace(SNUM(cnum
))) {
1078 strcpy(dname
,fname
);
1079 p
= strrchr(dname
,'/');
1081 if (sys_disk_free(dname
,&dum1
,&dum2
,&dum3
) <
1082 lp_minprintspace(SNUM(cnum
))) {
1083 fd_attempt_close(fd_ptr
);
1084 Files
[fnum
].fd_ptr
= 0;
1085 if(fd_ptr
->ref_count
== 0)
1094 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1095 fname
,strerror(errno
),flags
));
1096 /* Ensure the ref_count is decremented. */
1097 fd_attempt_close(fd_ptr
);
1098 check_for_pipe(fname
);
1102 if (fd_ptr
->fd
>= 0)
1106 if(fstat(fd_ptr
->fd
, &statbuf
) == -1) {
1107 /* Error - backout !! */
1108 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1109 fd_ptr
->fd
, fname
,strerror(errno
)));
1110 /* Ensure the ref_count is decremented. */
1111 fd_attempt_close(fd_ptr
);
1116 /* Set the correct entries in fd_ptr. */
1117 fd_ptr
->dev
= (int32
)sbuf
->st_dev
;
1118 fd_ptr
->inode
= (int32
)sbuf
->st_ino
;
1120 Files
[fnum
].fd_ptr
= fd_ptr
;
1121 Connections
[cnum
].num_files_open
++;
1122 Files
[fnum
].mode
= sbuf
->st_mode
;
1123 GetTimeOfDay(&Files
[fnum
].open_time
);
1124 Files
[fnum
].uid
= current_user
.id
;
1125 Files
[fnum
].size
= 0;
1126 Files
[fnum
].pos
= -1;
1127 Files
[fnum
].open
= True
;
1128 Files
[fnum
].mmap_ptr
= NULL
;
1129 Files
[fnum
].mmap_size
= 0;
1130 Files
[fnum
].can_lock
= True
;
1131 Files
[fnum
].can_read
= ((flags
& O_WRONLY
)==0);
1132 Files
[fnum
].can_write
= ((flags
& (O_WRONLY
|O_RDWR
))!=0);
1133 Files
[fnum
].share_mode
= 0;
1134 Files
[fnum
].share_pending
= False
;
1135 Files
[fnum
].print_file
= Connections
[cnum
].printer
;
1136 Files
[fnum
].modified
= False
;
1137 Files
[fnum
].cnum
= cnum
;
1138 string_set(&Files
[fnum
].name
,dos_to_unix(fname
,False
));
1139 Files
[fnum
].wbmpx_ptr
= NULL
;
1142 * If the printer is marked as postscript output a leading
1143 * file identifier to ensure the file is treated as a raw
1145 * This has a similar effect as CtrlD=0 in WIN.INI file.
1146 * tim@fsg.com 09/06/94
1148 if (Files
[fnum
].print_file
&& POSTSCRIPT(cnum
) &&
1149 Files
[fnum
].can_write
)
1151 DEBUG(3,("Writing postscript line\n"));
1152 write_file(fnum
,"%!\n",3);
1155 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1156 timestring(),Connections
[cnum
].user
,fname
,
1157 BOOLSTR(Files
[fnum
].can_read
),BOOLSTR(Files
[fnum
].can_write
),
1158 Connections
[cnum
].num_files_open
,fnum
));
1163 /* mmap it if read-only */
1164 if (!Files
[fnum
].can_write
)
1166 Files
[fnum
].mmap_size
= file_size(fname
);
1167 Files
[fnum
].mmap_ptr
= (char *)mmap(NULL
,Files
[fnum
].mmap_size
,
1168 PROT_READ
,MAP_SHARED
,Files
[fnum
].fd_ptr
->fd
,0);
1170 if (Files
[fnum
].mmap_ptr
== (char *)-1 || !Files
[fnum
].mmap_ptr
)
1172 DEBUG(3,("Failed to mmap() %s - %s\n",fname
,strerror(errno
)));
1173 Files
[fnum
].mmap_ptr
= NULL
;
1179 /*******************************************************************
1181 ********************************************************************/
1182 void sync_file(int fnum
)
1185 fsync(Files
[fnum
].fd_ptr
->fd
);
1189 /****************************************************************************
1190 run a file if it is a magic script
1191 ****************************************************************************/
1192 static void check_magic(int fnum
,int cnum
)
1194 if (!*lp_magicscript(SNUM(cnum
)))
1197 DEBUG(5,("checking magic for %s\n",Files
[fnum
].name
));
1201 if (!(p
= strrchr(Files
[fnum
].name
,'/')))
1202 p
= Files
[fnum
].name
;
1206 if (!strequal(lp_magicscript(SNUM(cnum
)),p
))
1212 pstring magic_output
;
1214 strcpy(fname
,Files
[fnum
].name
);
1216 if (*lp_magicoutput(SNUM(cnum
)))
1217 strcpy(magic_output
,lp_magicoutput(SNUM(cnum
)));
1219 sprintf(magic_output
,"%s.out",fname
);
1222 ret
= smbrun(fname
,magic_output
,False
);
1223 DEBUG(3,("Invoking magic command %s gave %d\n",fname
,ret
));
1229 /****************************************************************************
1230 close a file - possibly invalidating the read prediction
1231 ****************************************************************************/
1232 void close_file(int fnum
)
1234 int cnum
= Files
[fnum
].cnum
;
1235 invalidate_read_prediction(Files
[fnum
].fd_ptr
->fd
);
1236 Files
[fnum
].open
= False
;
1237 Connections
[cnum
].num_files_open
--;
1238 if(Files
[fnum
].wbmpx_ptr
)
1240 free((char *)Files
[fnum
].wbmpx_ptr
);
1241 Files
[fnum
].wbmpx_ptr
= NULL
;
1245 if(Files
[fnum
].mmap_ptr
)
1247 munmap(Files
[fnum
].mmap_ptr
,Files
[fnum
].mmap_size
);
1248 Files
[fnum
].mmap_ptr
= NULL
;
1252 if (lp_share_modes(SNUM(cnum
)))
1253 del_share_mode(fnum
);
1255 fd_attempt_close(Files
[fnum
].fd_ptr
);
1257 /* NT uses smbclose to start a print - weird */
1258 if (Files
[fnum
].print_file
)
1261 /* check for magic scripts */
1262 check_magic(fnum
,cnum
);
1264 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1265 timestring(),Connections
[cnum
].user
,Files
[fnum
].name
,
1266 Connections
[cnum
].num_files_open
));
1269 enum {AFAIL
,AREAD
,AWRITE
,AALL
};
1271 /*******************************************************************
1272 reproduce the share mode access table
1273 ********************************************************************/
1274 static int access_table(int new_deny
,int old_deny
,int old_mode
,
1275 int share_pid
,char *fname
)
1277 if (new_deny
== DENY_ALL
|| old_deny
== DENY_ALL
) return(AFAIL
);
1279 if (new_deny
== DENY_DOS
|| old_deny
== DENY_DOS
) {
1280 if (old_deny
== new_deny
&& share_pid
== getpid())
1283 if (old_mode
== 0) return(AREAD
);
1285 /* the new smbpub.zip spec says that if the file extension is
1286 .com, .dll, .exe or .sym then allow the open. I will force
1287 it to read-only as this seems sensible although the spec is
1288 a little unclear on this. */
1289 if ((fname
= strrchr(fname
,'.'))) {
1290 if (strequal(fname
,".com") ||
1291 strequal(fname
,".dll") ||
1292 strequal(fname
,".exe") ||
1293 strequal(fname
,".sym"))
1303 if (old_deny
==DENY_WRITE
&& old_mode
==0) return(AREAD
);
1304 if (old_deny
==DENY_READ
&& old_mode
==0) return(AWRITE
);
1305 if (old_deny
==DENY_NONE
&& old_mode
==0) return(AALL
);
1308 if (old_deny
==DENY_WRITE
&& old_mode
==1) return(AREAD
);
1309 if (old_deny
==DENY_READ
&& old_mode
==1) return(AWRITE
);
1310 if (old_deny
==DENY_NONE
&& old_mode
==1) return(AALL
);
1313 if (old_deny
==DENY_WRITE
) return(AREAD
);
1314 if (old_deny
==DENY_READ
) return(AWRITE
);
1315 if (old_deny
==DENY_NONE
) return(AALL
);
1321 /*******************************************************************
1322 check if the share mode on a file allows it to be deleted or unlinked
1323 return True if sharing doesn't prevent the operation
1324 ********************************************************************/
1325 BOOL
check_file_sharing(int cnum
,char *fname
)
1328 int share_mode
= get_share_mode_byname(cnum
,fname
,&pid
);
1330 if (!pid
|| !share_mode
) return(True
);
1332 if (share_mode
== DENY_DOS
)
1333 return(pid
== getpid());
1335 /* XXXX exactly what share mode combinations should be allowed for
1336 deleting/renaming? */
1340 /****************************************************************************
1342 Helper for open_file_shared.
1343 Truncate a file after checking locking; close file if locked.
1344 **************************************************************************/
1345 static void truncate_unless_locked(int fnum
, int cnum
)
1347 if (Files
[fnum
].can_write
){
1348 if (is_locked(fnum
,cnum
,0x3FFFFFFF,0)){
1351 unix_ERR_class
= ERRDOS
;
1352 unix_ERR_code
= ERRlock
;
1355 ftruncate(Files
[fnum
].fd_ptr
->fd
,0);
1360 /****************************************************************************
1361 open a file with a share mode
1362 ****************************************************************************/
1363 void open_file_shared(int fnum
,int cnum
,char *fname
,int share_mode
,int ofun
,
1364 int mode
,int *Access
,int *action
)
1368 int deny_mode
= (share_mode
>>4)&7;
1370 BOOL file_existed
= file_exist(fname
,&sbuf
);
1371 BOOL fcbopen
= False
;
1374 Files
[fnum
].open
= False
;
1375 Files
[fnum
].fd_ptr
= 0;
1377 /* this is for OS/2 EAs - try and say we don't support them */
1378 if (strstr(fname
,".+,;=[].")) {
1379 unix_ERR_class
= ERRDOS
;
1380 unix_ERR_code
= ERROR_EAS_NOT_SUPPORTED
;
1384 if ((ofun
& 0x3) == 0 && file_existed
) {
1391 if ((ofun
& 0x3) == 2)
1394 /* note that we ignore the append flag as
1395 append does not mean the same thing under dos and unix */
1397 switch (share_mode
&0xF)
1414 if (flags
!= O_RDONLY
&& file_existed
&&
1415 (!CAN_WRITE(cnum
) || IS_DOS_READONLY(dos_mode(cnum
,fname
,&sbuf
)))) {
1423 if (deny_mode
> DENY_NONE
&& deny_mode
!=DENY_FCB
) {
1424 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode
,fname
));
1429 if (deny_mode
== DENY_FCB
) deny_mode
= DENY_DOS
;
1431 if (lp_share_modes(SNUM(cnum
))) {
1435 old_share
= get_share_mode(cnum
,&sbuf
,&share_pid
);
1438 /* someone else has a share lock on it, check to see
1440 int old_open_mode
= old_share
&0xF;
1441 int old_deny_mode
= (old_share
>>4)&7;
1443 if (deny_mode
> 4 || old_deny_mode
> 4 || old_open_mode
> 2) {
1444 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1445 deny_mode
,old_deny_mode
,old_open_mode
,fname
));
1447 unix_ERR_class
= ERRDOS
;
1448 unix_ERR_code
= ERRbadshare
;
1453 int access_allowed
= access_table(deny_mode
,old_deny_mode
,old_open_mode
,
1456 if ((access_allowed
== AFAIL
) ||
1457 (!fcbopen
&& (access_allowed
== AREAD
&& flags
== O_RDWR
)) ||
1458 (access_allowed
== AREAD
&& flags
== O_WRONLY
) ||
1459 (access_allowed
== AWRITE
&& flags
== O_RDONLY
)) {
1460 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1461 deny_mode
,old_deny_mode
,old_open_mode
,
1465 unix_ERR_class
= ERRDOS
;
1466 unix_ERR_code
= ERRbadshare
;
1470 if (access_allowed
== AREAD
)
1473 if (access_allowed
== AWRITE
)
1479 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1480 flags
,flags2
,mode
));
1482 open_file(fnum
,cnum
,fname
,flags
|(flags2
&~(O_TRUNC
)),mode
,file_existed
? &sbuf
: 0);
1483 if (!Files
[fnum
].open
&& flags
==O_RDWR
&& errno
!=ENOENT
&& fcbopen
) {
1485 open_file(fnum
,cnum
,fname
,flags
,mode
,file_existed
? &sbuf
: 0 );
1488 if (Files
[fnum
].open
) {
1502 Files
[fnum
].share_mode
= (deny_mode
<<4) | open_mode
;
1503 Files
[fnum
].share_pending
= True
;
1506 (*Access
) = open_mode
;
1510 if (file_existed
&& !(flags2
& O_TRUNC
)) *action
= 1;
1511 if (!file_existed
) *action
= 2;
1512 if (file_existed
&& (flags2
& O_TRUNC
)) *action
= 3;
1516 share_mode_pending
= True
;
1518 if ((flags2
&O_TRUNC
) && file_existed
)
1519 truncate_unless_locked(fnum
,cnum
);
1525 /*******************************************************************
1526 check for files that we should now set our share modes on
1527 ********************************************************************/
1528 static void check_share_modes(void)
1531 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
1532 if(Files
[i
].open
&& Files
[i
].share_pending
) {
1533 if (lp_share_modes(SNUM(Files
[i
].cnum
))) {
1535 get_share_mode_by_fnum(Files
[i
].cnum
,i
,&pid
);
1537 set_share_mode(i
,Files
[i
].share_mode
);
1538 Files
[i
].share_pending
= False
;
1541 Files
[i
].share_pending
= False
;
1547 /****************************************************************************
1548 seek a file. Try to avoid the seek if possible
1549 ****************************************************************************/
1550 int seek_file(int fnum
,int pos
)
1553 if (Files
[fnum
].print_file
&& POSTSCRIPT(Files
[fnum
].cnum
))
1556 Files
[fnum
].pos
= lseek(Files
[fnum
].fd_ptr
->fd
,pos
+offset
,SEEK_SET
) - offset
;
1557 return(Files
[fnum
].pos
);
1560 /****************************************************************************
1562 ****************************************************************************/
1563 int read_file(int fnum
,char *data
,int pos
,int n
)
1567 if (!Files
[fnum
].can_write
)
1569 ret
= read_predict(Files
[fnum
].fd_ptr
->fd
,pos
,data
,NULL
,n
);
1577 if (Files
[fnum
].mmap_ptr
)
1579 int num
= MIN(n
,Files
[fnum
].mmap_size
-pos
);
1582 memcpy(data
,Files
[fnum
].mmap_ptr
+pos
,num
);
1594 if (seek_file(fnum
,pos
) != pos
)
1596 DEBUG(3,("Failed to seek to %d\n",pos
));
1601 readret
= read(Files
[fnum
].fd_ptr
->fd
,data
,n
);
1602 if (readret
> 0) ret
+= readret
;
1609 /****************************************************************************
1611 ****************************************************************************/
1612 int write_file(int fnum
,char *data
,int n
)
1614 if (!Files
[fnum
].can_write
) {
1619 if (!Files
[fnum
].modified
) {
1621 Files
[fnum
].modified
= True
;
1622 if (fstat(Files
[fnum
].fd_ptr
->fd
,&st
) == 0) {
1623 int dosmode
= dos_mode(Files
[fnum
].cnum
,Files
[fnum
].name
,&st
);
1624 if (MAP_ARCHIVE(Files
[fnum
].cnum
) && !IS_DOS_ARCHIVE(dosmode
)) {
1625 dos_chmod(Files
[fnum
].cnum
,Files
[fnum
].name
,dosmode
| aARCH
,&st
);
1630 return(write_data(Files
[fnum
].fd_ptr
->fd
,data
,n
));
1634 /****************************************************************************
1635 load parameters specific to a connection/service
1636 ****************************************************************************/
1637 BOOL
become_service(int cnum
,BOOL do_chdir
)
1639 extern char magic_char
;
1640 static int last_cnum
= -1;
1643 if (!OPEN_CNUM(cnum
))
1649 Connections
[cnum
].lastused
= smb_last_time
;
1654 ChDir(Connections
[cnum
].connectpath
) != 0 &&
1655 ChDir(Connections
[cnum
].origpath
) != 0)
1657 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1658 Connections
[cnum
].connectpath
,cnum
));
1662 if (cnum
== last_cnum
)
1667 case_default
= lp_defaultcase(snum
);
1668 case_preserve
= lp_preservecase(snum
);
1669 short_case_preserve
= lp_shortpreservecase(snum
);
1670 case_mangle
= lp_casemangle(snum
);
1671 case_sensitive
= lp_casesensitive(snum
);
1672 magic_char
= lp_magicchar(snum
);
1673 use_mangled_map
= (*lp_mangled_map(snum
) ? True
:False
);
1678 /****************************************************************************
1679 find a service entry
1680 ****************************************************************************/
1681 int find_service(char *service
)
1685 string_sub(service
,"\\","/");
1687 iService
= lp_servicenumber(service
);
1689 /* now handle the special case of a home directory */
1692 char *phome_dir
= get_home_dir(service
);
1693 DEBUG(3,("checking for home directory %s gave %s\n",service
,
1694 phome_dir
?phome_dir
:"(NULL)"));
1698 if ((iHomeService
= lp_servicenumber(HOMES_NAME
)) >= 0)
1700 lp_add_home(service
,iHomeService
,phome_dir
);
1701 iService
= lp_servicenumber(service
);
1706 /* If we still don't have a service, attempt to add it as a printer. */
1709 int iPrinterService
;
1711 if ((iPrinterService
= lp_servicenumber(PRINTERS_NAME
)) >= 0)
1715 DEBUG(3,("checking whether %s is a valid printer name...\n", service
));
1717 if ((pszTemp
!= NULL
) && pcap_printername_ok(service
, pszTemp
))
1719 DEBUG(3,("%s is a valid printer name\n", service
));
1720 DEBUG(3,("adding %s as a printer service\n", service
));
1721 lp_add_printer(service
,iPrinterService
);
1722 iService
= lp_servicenumber(service
);
1724 DEBUG(0,("failed to add %s as a printer service!\n", service
));
1727 DEBUG(3,("%s is not a valid printer name\n", service
));
1731 /* just possibly it's a default service? */
1734 char *defservice
= lp_defaultservice();
1735 if (defservice
&& *defservice
&& !strequal(defservice
,service
)) {
1736 iService
= find_service(defservice
);
1737 if (iService
>= 0) {
1738 string_sub(service
,"_","/");
1739 iService
= lp_add_service(service
,iService
);
1745 if (!VALID_SNUM(iService
))
1747 DEBUG(0,("Invalid snum %d for %s\n",iService
,service
));
1752 DEBUG(3,("find_service() failed to find service %s\n", service
));
1758 /****************************************************************************
1759 create an error packet from a cached error.
1760 ****************************************************************************/
1761 int cached_error_packet(char *inbuf
,char *outbuf
,int fnum
,int line
)
1763 write_bmpx_struct
*wbmpx
= Files
[fnum
].wbmpx_ptr
;
1765 int32 eclass
= wbmpx
->wr_errclass
;
1766 int32 err
= wbmpx
->wr_error
;
1768 /* We can now delete the auxiliary struct */
1769 free((char *)wbmpx
);
1770 Files
[fnum
].wbmpx_ptr
= NULL
;
1771 return error_packet(inbuf
,outbuf
,eclass
,err
,line
);
1780 } unix_smb_errmap
[] =
1782 {EPERM
,ERRDOS
,ERRnoaccess
},
1783 {EACCES
,ERRDOS
,ERRnoaccess
},
1784 {ENOENT
,ERRDOS
,ERRbadfile
},
1785 {EIO
,ERRHRD
,ERRgeneral
},
1786 {EBADF
,ERRSRV
,ERRsrverror
},
1787 {EINVAL
,ERRSRV
,ERRsrverror
},
1788 {EEXIST
,ERRDOS
,ERRfilexists
},
1789 {ENFILE
,ERRDOS
,ERRnofids
},
1790 {EMFILE
,ERRDOS
,ERRnofids
},
1791 {ENOSPC
,ERRHRD
,ERRdiskfull
},
1793 {EDQUOT
,ERRHRD
,ERRdiskfull
},
1796 {ENOTEMPTY
,ERRDOS
,ERRnoaccess
},
1799 {EXDEV
,ERRDOS
,ERRdiffdevice
},
1801 {EROFS
,ERRHRD
,ERRnowrite
},
1806 /****************************************************************************
1807 create an error packet from errno
1808 ****************************************************************************/
1809 int unix_error_packet(char *inbuf
,char *outbuf
,int def_class
,uint32 def_code
,int line
)
1811 int eclass
=def_class
;
1815 if (unix_ERR_class
!= SUCCESS
)
1817 eclass
= unix_ERR_class
;
1818 ecode
= unix_ERR_code
;
1819 unix_ERR_class
= SUCCESS
;
1824 while (unix_smb_errmap
[i
].smbclass
!= 0)
1826 if (unix_smb_errmap
[i
].unixerror
== errno
)
1828 eclass
= unix_smb_errmap
[i
].smbclass
;
1829 ecode
= unix_smb_errmap
[i
].smbcode
;
1836 return(error_packet(inbuf
,outbuf
,eclass
,ecode
,line
));
1840 /****************************************************************************
1841 create an error packet. Normally called using the ERROR() macro
1842 ****************************************************************************/
1843 int error_packet(char *inbuf
,char *outbuf
,int error_class
,uint32 error_code
,int line
)
1845 int outsize
= set_message(outbuf
,0,0,True
);
1847 cmd
= CVAL(inbuf
,smb_com
);
1849 CVAL(outbuf
,smb_rcls
) = error_class
;
1850 SSVAL(outbuf
,smb_err
,error_code
);
1852 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1855 (int)CVAL(inbuf
,smb_com
),
1856 smb_fn_name(CVAL(inbuf
,smb_com
)),
1861 DEBUG(3,("error string = %s\n",strerror(errno
)));
1867 #ifndef SIGCLD_IGNORE
1868 /****************************************************************************
1869 this prevents zombie child processes
1870 ****************************************************************************/
1871 static int sig_cld()
1873 static int depth
= 0;
1876 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1882 BlockSignals(True
,SIGCLD
);
1883 DEBUG(5,("got SIGCLD\n"));
1886 while (sys_waitpid((pid_t
)-1,(int *)NULL
, WNOHANG
) > 0);
1890 /* Stevens, Adv. Unix Prog. says that on system V you must call
1891 wait before reinstalling the signal handler, because the kernel
1892 calls the handler from within the signal-call when there is a
1893 child that has exited. This would lead to an infinite recursion
1894 if done vice versa. */
1896 #ifndef DONT_REINSTALL_SIG
1897 #ifdef SIGCLD_IGNORE
1898 signal(SIGCLD
, SIG_IGN
);
1900 signal(SIGCLD
, SIGNAL_CAST sig_cld
);
1905 while (wait3(WAIT3_CAST1 NULL
, WNOHANG
, WAIT3_CAST2 NULL
) > 0);
1908 BlockSignals(False
,SIGCLD
);
1913 /****************************************************************************
1914 this is called when the client exits abruptly
1915 **************************************************************************/
1916 static int sig_pipe()
1918 extern int password_client
;
1919 BlockSignals(True
,SIGPIPE
);
1921 if (password_client
!= -1) {
1922 DEBUG(3,("lost connection to password server\n"));
1923 close(password_client
);
1924 password_client
= -1;
1925 #ifndef DONT_REINSTALL_SIG
1926 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
1928 BlockSignals(False
,SIGPIPE
);
1932 exit_server("Got sigpipe\n");
1936 /****************************************************************************
1937 open the socket communication
1938 ****************************************************************************/
1939 static BOOL
open_sockets(BOOL is_daemon
,int port
)
1946 struct sockaddr addr
;
1947 int in_addrlen
= sizeof(addr
);
1950 #ifdef SIGCLD_IGNORE
1951 signal(SIGCLD
, SIG_IGN
);
1953 signal(SIGCLD
, SIGNAL_CAST sig_cld
);
1956 /* open an incoming socket */
1957 s
= open_socket_in(SOCK_STREAM
, port
, 0,interpret_addr(lp_socket_address()));
1961 /* ready to listen */
1962 if (listen(s
, 5) == -1)
1964 DEBUG(0,("listen: %s",strerror(errno
)));
1972 /* now accept incoming connections - forking a new process
1973 for each incoming connection */
1974 DEBUG(2,("waiting for a connection\n"));
1977 Client
= accept(s
,&addr
,&in_addrlen
);
1979 if (Client
== -1 && errno
== EINTR
)
1984 DEBUG(0,("accept: %s",strerror(errno
)));
1988 #ifdef NO_FORK_DEBUG
1989 #ifndef NO_SIGNAL_TEST
1990 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
1991 signal(SIGCLD
, SIGNAL_CAST SIG_DFL
);
1995 if (Client
!= -1 && fork()==0)
1997 #ifndef NO_SIGNAL_TEST
1998 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
1999 signal(SIGCLD
, SIGNAL_CAST SIG_DFL
);
2001 /* close the listening socket */
2004 /* close our standard file descriptors */
2008 set_socket_options(Client
,"SO_KEEPALIVE");
2009 set_socket_options(Client
,user_socket_options
);
2013 close(Client
); /* The parent doesn't need this socket */
2019 /* We will abort gracefully when the client or remote system
2021 #ifndef NO_SIGNAL_TEST
2022 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
2026 /* close our standard file descriptors */
2029 set_socket_options(Client
,"SO_KEEPALIVE");
2030 set_socket_options(Client
,user_socket_options
);
2037 /****************************************************************************
2038 check if a snum is in use
2039 ****************************************************************************/
2040 BOOL
snum_used(int snum
)
2043 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2044 if (OPEN_CNUM(i
) && (SNUM(i
) == snum
))
2049 /****************************************************************************
2050 reload the services file
2051 **************************************************************************/
2052 BOOL
reload_services(BOOL test
)
2059 strcpy(fname
,lp_configfile());
2060 if (file_exist(fname
,NULL
) && !strcsequal(fname
,servicesf
))
2062 strcpy(servicesf
,fname
);
2069 if (test
&& !lp_file_list_changed())
2072 lp_killunused(snum_used
);
2074 ret
= lp_load(servicesf
,False
);
2076 /* perhaps the config filename is now set */
2078 reload_services(True
);
2087 set_socket_options(Client
,"SO_KEEPALIVE");
2088 set_socket_options(Client
,user_socket_options
);
2092 create_mangled_stack(lp_mangledstack());
2094 /* this forces service parameters to be flushed */
2095 become_service(-1,True
);
2102 /****************************************************************************
2103 this prevents zombie child processes
2104 ****************************************************************************/
2105 static int sig_hup()
2107 BlockSignals(True
,SIGHUP
);
2108 DEBUG(0,("Got SIGHUP\n"));
2109 reload_services(False
);
2110 #ifndef DONT_REINSTALL_SIG
2111 signal(SIGHUP
,SIGNAL_CAST sig_hup
);
2113 BlockSignals(False
,SIGHUP
);
2117 /****************************************************************************
2118 Setup the groups a user belongs to.
2119 ****************************************************************************/
2120 int setup_groups(char *user
, int uid
, int gid
, int *p_ngroups
,
2121 int **p_igroups
, gid_t
**p_groups
)
2123 if (-1 == initgroups(user
,gid
))
2127 DEBUG(0,("Unable to initgroups!\n"));
2128 if (gid
< 0 || gid
> 16000 || uid
< 0 || uid
> 16000)
2129 DEBUG(0,("This is probably a problem with the account %s\n",user
));
2137 ngroups
= getgroups(0,&grp
);
2140 igroups
= (int *)malloc(sizeof(int)*ngroups
);
2141 for (i
=0;i
<ngroups
;i
++)
2142 igroups
[i
] = 0x42424242;
2143 ngroups
= getgroups(ngroups
,(gid_t
*)igroups
);
2145 if (igroups
[0] == 0x42424242)
2148 *p_ngroups
= ngroups
;
2150 /* The following bit of code is very strange. It is due to the
2151 fact that some OSes use int* and some use gid_t* for
2152 getgroups, and some (like SunOS) use both, one in prototypes,
2153 and one in man pages and the actual code. Thus we detect it
2154 dynamically using some very ugly code */
2157 /* does getgroups return ints or gid_t ?? */
2158 static BOOL groups_use_ints
= True
;
2160 if (groups_use_ints
&&
2162 SVAL(igroups
,2) == 0x4242)
2163 groups_use_ints
= False
;
2165 for (i
=0;groups_use_ints
&& i
<ngroups
;i
++)
2166 if (igroups
[i
] == 0x42424242)
2167 groups_use_ints
= False
;
2169 if (groups_use_ints
)
2171 *p_igroups
= igroups
;
2172 *p_groups
= (gid_t
*)igroups
;
2176 gid_t
*groups
= (gid_t
*)igroups
;
2177 igroups
= (int *)malloc(sizeof(int)*ngroups
);
2178 for (i
=0;i
<ngroups
;i
++)
2179 igroups
[i
] = groups
[i
];
2180 *p_igroups
= igroups
;
2181 *p_groups
= (gid_t
*)groups
;
2184 DEBUG(3,("%s is in %d groups\n",user
,ngroups
));
2185 for (i
=0;i
<ngroups
;i
++)
2186 DEBUG(3,("%d ",igroups
[i
]));
2192 /****************************************************************************
2193 make a connection to a service
2194 ****************************************************************************/
2195 int make_connection(char *service
,char *user
,char *password
, int pwlen
, char *dev
,uint16 vuid
)
2199 struct passwd
*pass
= NULL
;
2200 connection_struct
*pcon
;
2203 static BOOL first_connection
= True
;
2207 snum
= find_service(service
);
2210 if (strequal(service
,"IPC$"))
2212 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2216 DEBUG(0,("%s couldn't find service %s\n",timestring(),service
));
2220 if (strequal(service
,HOMES_NAME
))
2222 if (*user
&& Get_Pwnam(user
,True
))
2223 return(make_connection(user
,user
,password
,pwlen
,dev
,vuid
));
2225 if (validated_username(vuid
))
2227 strcpy(user
,validated_username(vuid
));
2228 return(make_connection(user
,user
,password
,pwlen
,dev
,vuid
));
2232 if (!lp_snum_ok(snum
) || !check_access(snum
)) {
2236 /* you can only connect to the IPC$ service as an ipc device */
2237 if (strequal(service
,"IPC$"))
2240 if (*dev
== '?' || !*dev
)
2242 if (lp_print_ok(snum
))
2243 strcpy(dev
,"LPT1:");
2248 /* if the request is as a printer and you can't print then refuse */
2250 if (!lp_print_ok(snum
) && (strncmp(dev
,"LPT",3) == 0)) {
2251 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2255 /* lowercase the user name */
2258 /* add it as a possible user name */
2259 add_session_user(service
);
2261 /* shall we let them in? */
2262 if (!authorise_login(snum
,user
,password
,pwlen
,&guest
,&force
,vuid
))
2264 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service
));
2268 cnum
= find_free_connection(str_checksum(service
) + str_checksum(user
));
2271 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2275 pcon
= &Connections
[cnum
];
2276 bzero((char *)pcon
,sizeof(*pcon
));
2278 /* find out some info about the user */
2279 pass
= Get_Pwnam(user
,True
);
2283 DEBUG(0,("%s couldn't find account %s\n",timestring(),user
));
2287 pcon
->read_only
= lp_readonly(snum
);
2291 StrnCpy(list
,lp_readlist(snum
),sizeof(pstring
)-1);
2292 string_sub(list
,"%S",service
);
2294 if (user_in_list(user
,list
))
2295 pcon
->read_only
= True
;
2297 StrnCpy(list
,lp_writelist(snum
),sizeof(pstring
)-1);
2298 string_sub(list
,"%S",service
);
2300 if (user_in_list(user
,list
))
2301 pcon
->read_only
= False
;
2304 /* admin user check */
2305 if (user_in_list(user
,lp_admin_users(snum
)) &&
2308 pcon
->admin_user
= True
;
2309 DEBUG(0,("%s logged in as admin user (root privileges)\n",user
));
2312 pcon
->admin_user
= False
;
2314 pcon
->force_user
= force
;
2316 pcon
->uid
= pass
->pw_uid
;
2317 pcon
->gid
= pass
->pw_gid
;
2318 pcon
->num_files_open
= 0;
2319 pcon
->lastused
= time(NULL
);
2320 pcon
->service
= snum
;
2322 pcon
->printer
= (strncmp(dev
,"LPT",3) == 0);
2323 pcon
->ipc
= (strncmp(dev
,"IPC",3) == 0);
2324 pcon
->dirptr
= NULL
;
2325 string_set(&pcon
->dirpath
,"");
2326 string_set(&pcon
->user
,user
);
2329 if (*lp_force_group(snum
))
2334 StrnCpy(gname
,lp_force_group(snum
),sizeof(pstring
)-1);
2335 /* default service may be a group name */
2336 string_sub(gname
,"%S",service
);
2337 gptr
= (struct group
*)getgrnam(gname
);
2341 pcon
->gid
= gptr
->gr_gid
;
2342 DEBUG(3,("Forced group %s\n",gname
));
2345 DEBUG(1,("Couldn't find group %s\n",gname
));
2349 if (*lp_force_user(snum
))
2351 struct passwd
*pass2
;
2353 strcpy(fuser
,lp_force_user(snum
));
2354 pass2
= (struct passwd
*)Get_Pwnam(fuser
,True
);
2357 pcon
->uid
= pass2
->pw_uid
;
2358 string_set(&pcon
->user
,fuser
);
2360 pcon
->force_user
= True
;
2361 DEBUG(3,("Forced user %s\n",fuser
));
2364 DEBUG(1,("Couldn't find user %s\n",fuser
));
2369 strcpy(s
,lp_pathname(snum
));
2370 standard_sub(cnum
,s
);
2371 string_set(&pcon
->connectpath
,s
);
2372 DEBUG(3,("Connect path is %s\n",s
));
2375 /* groups stuff added by ih */
2377 pcon
->groups
= NULL
;
2381 /* Find all the groups this uid is in and store them. Used by become_user() */
2382 setup_groups(pcon
->user
,pcon
->uid
,pcon
->gid
,&pcon
->ngroups
,&pcon
->igroups
,&pcon
->groups
);
2384 /* check number of connections */
2385 if (!claim_connection(cnum
,
2386 lp_servicename(SNUM(cnum
)),
2387 lp_max_connections(SNUM(cnum
)),False
))
2389 DEBUG(1,("too many connections - rejected\n"));
2393 if (lp_status(SNUM(cnum
)))
2394 claim_connection(cnum
,"STATUS.",MAXSTATUS
,first_connection
);
2396 first_connection
= False
;
2401 /* execute any "root preexec = " line */
2402 if (*lp_rootpreexec(SNUM(cnum
)))
2405 strcpy(cmd
,lp_rootpreexec(SNUM(cnum
)));
2406 standard_sub(cnum
,cmd
);
2407 DEBUG(5,("cmd=%s\n",cmd
));
2408 smbrun(cmd
,NULL
,False
);
2411 if (!become_user(cnum
,pcon
->vuid
))
2413 DEBUG(0,("Can't become connected user!\n"));
2415 if (!IS_IPC(cnum
)) {
2416 yield_connection(cnum
,
2417 lp_servicename(SNUM(cnum
)),
2418 lp_max_connections(SNUM(cnum
)));
2419 if (lp_status(SNUM(cnum
))) yield_connection(cnum
,"STATUS.",MAXSTATUS
);
2424 if (ChDir(pcon
->connectpath
) != 0)
2426 DEBUG(0,("Can't change directory to %s (%s)\n",
2427 pcon
->connectpath
,strerror(errno
)));
2430 if (!IS_IPC(cnum
)) {
2431 yield_connection(cnum
,
2432 lp_servicename(SNUM(cnum
)),
2433 lp_max_connections(SNUM(cnum
)));
2434 if (lp_status(SNUM(cnum
))) yield_connection(cnum
,"STATUS.",MAXSTATUS
);
2439 string_set(&pcon
->origpath
,pcon
->connectpath
);
2441 #if SOFTLINK_OPTIMISATION
2442 /* resolve any soft links early */
2445 strcpy(s
,pcon
->connectpath
);
2447 string_set(&pcon
->connectpath
,s
);
2448 ChDir(pcon
->connectpath
);
2452 num_connections_open
++;
2453 add_session_user(user
);
2455 /* execute any "preexec = " line */
2456 if (*lp_preexec(SNUM(cnum
)))
2459 strcpy(cmd
,lp_preexec(SNUM(cnum
)));
2460 standard_sub(cnum
,cmd
);
2461 smbrun(cmd
,NULL
,False
);
2464 /* we've finished with the sensitive stuff */
2468 DEBUG(IS_IPC(cnum
)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2472 lp_servicename(SNUM(cnum
)),user
,
2482 /****************************************************************************
2483 find first available file slot
2484 ****************************************************************************/
2485 int find_free_file(void )
2488 /* we start at 1 here for an obscure reason I can't now remember,
2489 but I think is important :-) */
2490 for (i
=1;i
<MAX_OPEN_FILES
;i
++)
2493 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2497 /****************************************************************************
2498 find first available connection slot, starting from a random position.
2499 The randomisation stops problems with the server dieing and clients
2500 thinking the server is still available.
2501 ****************************************************************************/
2502 static int find_free_connection(int hash
)
2506 hash
= (hash
% (MAX_CONNECTIONS
-2))+1;
2510 for (i
=hash
+1;i
!=hash
;)
2512 if (!Connections
[i
].open
&& Connections
[i
].used
== used
)
2514 DEBUG(3,("found free connection number %d\n",i
));
2518 if (i
== MAX_CONNECTIONS
)
2528 DEBUG(1,("ERROR! Out of connection structures\n"));
2533 /****************************************************************************
2534 reply for the core protocol
2535 ****************************************************************************/
2536 int reply_corep(char *outbuf
)
2538 int outsize
= set_message(outbuf
,1,0,True
);
2540 Protocol
= PROTOCOL_CORE
;
2546 /****************************************************************************
2547 reply for the coreplus protocol
2548 ****************************************************************************/
2549 int reply_coreplus(char *outbuf
)
2551 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2552 int outsize
= set_message(outbuf
,13,0,True
);
2553 SSVAL(outbuf
,smb_vwv5
,raw
); /* tell redirector we support
2554 readbraw and writebraw (possibly) */
2555 CVAL(outbuf
,smb_flg
) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2556 SSVAL(outbuf
,smb_vwv1
,0x1); /* user level security, don't encrypt */
2558 Protocol
= PROTOCOL_COREPLUS
;
2564 /****************************************************************************
2565 reply for the lanman 1.0 protocol
2566 ****************************************************************************/
2567 int reply_lanman1(char *outbuf
)
2569 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2571 BOOL doencrypt
= SMBENCRYPT();
2572 time_t t
= time(NULL
);
2574 if (lp_security()>=SEC_USER
) secword
|= 1;
2575 if (doencrypt
) secword
|= 2;
2577 set_message(outbuf
,13,doencrypt
?8:0,True
);
2578 SSVAL(outbuf
,smb_vwv1
,secword
);
2580 /* Create a token value and add it to the outgoing packet. */
2582 generate_next_challenge(smb_buf(outbuf
));
2585 Protocol
= PROTOCOL_LANMAN1
;
2587 if (lp_security() == SEC_SERVER
&& server_cryptkey(outbuf
)) {
2588 DEBUG(3,("using password server validation\n"));
2590 if (doencrypt
) set_challenge(smb_buf(outbuf
));
2594 CVAL(outbuf
,smb_flg
) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2595 SSVAL(outbuf
,smb_vwv2
,maxxmit
);
2596 SSVAL(outbuf
,smb_vwv3
,lp_maxmux()); /* maxmux */
2597 SSVAL(outbuf
,smb_vwv4
,1);
2598 SSVAL(outbuf
,smb_vwv5
,raw
); /* tell redirector we support
2599 readbraw writebraw (possibly) */
2600 SIVAL(outbuf
,smb_vwv6
,getpid());
2601 SSVAL(outbuf
,smb_vwv10
, TimeDiff(t
)/60);
2603 put_dos_date(outbuf
,smb_vwv8
,t
);
2605 return (smb_len(outbuf
)+4);
2609 /****************************************************************************
2610 reply for the lanman 2.0 protocol
2611 ****************************************************************************/
2612 int reply_lanman2(char *outbuf
)
2614 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2616 BOOL doencrypt
= SMBENCRYPT();
2617 time_t t
= time(NULL
);
2619 if (lp_security()>=SEC_USER
) secword
|= 1;
2620 if (doencrypt
) secword
|= 2;
2622 set_message(outbuf
,13,doencrypt
?8:0,True
);
2623 SSVAL(outbuf
,smb_vwv1
,secword
);
2625 /* Create a token value and add it to the outgoing packet. */
2627 generate_next_challenge(smb_buf(outbuf
));
2630 SIVAL(outbuf
,smb_vwv6
,getpid());
2632 Protocol
= PROTOCOL_LANMAN2
;
2634 if (lp_security() == SEC_SERVER
&& server_cryptkey(outbuf
)) {
2635 DEBUG(3,("using password server validation\n"));
2637 if (doencrypt
) set_challenge(smb_buf(outbuf
));
2641 CVAL(outbuf
,smb_flg
) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2642 SSVAL(outbuf
,smb_vwv2
,maxxmit
);
2643 SSVAL(outbuf
,smb_vwv3
,lp_maxmux());
2644 SSVAL(outbuf
,smb_vwv4
,1);
2645 SSVAL(outbuf
,smb_vwv5
,raw
); /* readbraw and/or writebraw */
2646 SSVAL(outbuf
,smb_vwv10
, TimeDiff(t
)/60);
2647 put_dos_date(outbuf
,smb_vwv8
,t
);
2649 return (smb_len(outbuf
)+4);
2652 /****************************************************************************
2653 reply for the nt protocol
2654 ****************************************************************************/
2655 int reply_nt1(char *outbuf
)
2657 int capabilities
=0x300; /* has dual names + lock_and_read */
2659 BOOL doencrypt
= SMBENCRYPT();
2660 time_t t
= time(NULL
);
2662 if (lp_security()>=SEC_USER
) secword
|= 1;
2663 if (doencrypt
) secword
|= 2;
2665 set_message(outbuf
,17,doencrypt
?8:0,True
);
2666 CVAL(outbuf
,smb_vwv1
) = secword
;
2668 /* Create a token value and add it to the outgoing packet. */
2670 generate_next_challenge(smb_buf(outbuf
));
2671 /* Tell the nt machine how long the challenge is. */
2672 SSVALS(outbuf
,smb_vwv16
+1,8);
2676 SIVAL(outbuf
,smb_vwv7
+1,getpid()); /* session key */
2678 Protocol
= PROTOCOL_NT1
;
2680 if (lp_security() == SEC_SERVER
&& server_cryptkey(outbuf
)) {
2681 DEBUG(3,("using password server validation\n"));
2683 if (doencrypt
) set_challenge(smb_buf(outbuf
));
2687 if (lp_readraw() && lp_writeraw())
2690 SSVAL(outbuf
,smb_vwv1
+1,lp_maxmux()); /* maxmpx */
2691 SSVAL(outbuf
,smb_vwv2
+1,1); /* num vcs */
2692 SIVAL(outbuf
,smb_vwv3
+1,0xFFFF); /* max buffer */
2693 SIVAL(outbuf
,smb_vwv5
+1,0xFFFF); /* raw size */
2694 SIVAL(outbuf
,smb_vwv9
+1,capabilities
); /* capabilities */
2695 put_long_date(outbuf
+smb_vwv11
+1,t
);
2696 SSVALS(outbuf
,smb_vwv15
+1,TimeDiff(t
)/60);
2698 return (smb_len(outbuf
)+4);
2702 /* these are the protocol lists used for auto architecture detection:
2705 protocol [PC NETWORK PROGRAM 1.0]
2706 protocol [XENIX CORE]
2707 protocol [MICROSOFT NETWORKS 1.03]
2708 protocol [LANMAN1.0]
2709 protocol [Windows for Workgroups 3.1a]
2710 protocol [LM1.2X002]
2711 protocol [LANMAN2.1]
2712 protocol [NT LM 0.12]
2715 protocol [PC NETWORK PROGRAM 1.0]
2716 protocol [XENIX CORE]
2717 protocol [MICROSOFT NETWORKS 1.03]
2718 protocol [LANMAN1.0]
2719 protocol [Windows for Workgroups 3.1a]
2720 protocol [LM1.2X002]
2721 protocol [LANMAN2.1]
2722 protocol [NT LM 0.12]
2725 protocol [PC NETWORK PROGRAM 1.0]
2726 protocol [XENIX CORE]
2727 protocol [LANMAN1.0]
2728 protocol [LM1.2X002]
2729 protocol [LANMAN2.1]
2733 * Modified to recognize the architecture of the remote machine better.
2735 * This appears to be the matrix of which protocol is used by which
2737 Protocol WfWg Win95 WinNT OS/2
2738 PC NETWORK PROGRAM 1.0 1 1 1 1
2740 MICROSOFT NETWORKS 3.0 2 2
2742 MICROSOFT NETWORKS 1.03 3
2745 Windows for Workgroups 3.1a 5 5 5
2750 * tim@fsg.com 09/29/95
2753 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2754 #define ARCH_WIN95 0x2
2755 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2756 #define ARCH_WINNT 0x8
2757 #define ARCH_SAMBA 0x10
2759 #define ARCH_ALL 0x1F
2761 /* List of supported protocols, most desired first */
2765 int (*proto_reply_fn
)(char *);
2767 } supported_protocols
[] = {
2768 {"NT LANMAN 1.0", "NT1", reply_nt1
, PROTOCOL_NT1
},
2769 {"NT LM 0.12", "NT1", reply_nt1
, PROTOCOL_NT1
},
2770 {"LM1.2X002", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
2771 {"Samba", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
2772 {"DOS LM1.2X002", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
2773 {"LANMAN1.0", "LANMAN1", reply_lanman1
, PROTOCOL_LANMAN1
},
2774 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1
, PROTOCOL_LANMAN1
},
2775 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus
, PROTOCOL_COREPLUS
},
2776 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep
, PROTOCOL_CORE
},
2781 /****************************************************************************
2783 ****************************************************************************/
2784 static int reply_negprot(char *inbuf
,char *outbuf
)
2786 extern fstring remote_arch
;
2787 int outsize
= set_message(outbuf
,1,0,True
);
2792 int bcc
= SVAL(smb_buf(inbuf
),-2);
2793 int arch
= ARCH_ALL
;
2795 p
= smb_buf(inbuf
)+1;
2796 while (p
< (smb_buf(inbuf
) + bcc
))
2799 DEBUG(3,("Requested protocol [%s]\n",p
));
2800 if (strcsequal(p
,"Windows for Workgroups 3.1a"))
2801 arch
&= ( ARCH_WFWG
| ARCH_WIN95
| ARCH_WINNT
);
2802 else if (strcsequal(p
,"DOS LM1.2X002"))
2803 arch
&= ( ARCH_WFWG
| ARCH_WIN95
);
2804 else if (strcsequal(p
,"DOS LANMAN2.1"))
2805 arch
&= ( ARCH_WFWG
| ARCH_WIN95
);
2806 else if (strcsequal(p
,"NT LM 0.12"))
2807 arch
&= ( ARCH_WIN95
| ARCH_WINNT
);
2808 else if (strcsequal(p
,"LANMAN2.1"))
2809 arch
&= ( ARCH_WINNT
| ARCH_OS2
);
2810 else if (strcsequal(p
,"LM1.2X002"))
2811 arch
&= ( ARCH_WINNT
| ARCH_OS2
);
2812 else if (strcsequal(p
,"MICROSOFT NETWORKS 1.03"))
2814 else if (strcsequal(p
,"XENIX CORE"))
2815 arch
&= ( ARCH_WINNT
| ARCH_OS2
);
2816 else if (strcsequal(p
,"Samba")) {
2826 strcpy(remote_arch
,"Samba");
2829 strcpy(remote_arch
,"WfWg");
2832 strcpy(remote_arch
,"Win95");
2835 strcpy(remote_arch
,"WinNT");
2838 strcpy(remote_arch
,"OS2");
2841 strcpy(remote_arch
,"UNKNOWN");
2845 /* possibly reload - change of architecture */
2846 reload_services(True
);
2848 /* a special case to stop password server loops */
2849 if (Index
== 1 && strequal(remote_machine
,myhostname
) &&
2850 lp_security()==SEC_SERVER
)
2851 exit_server("Password server loop!");
2853 /* Check for protocols, most desirable first */
2854 for (protocol
= 0; supported_protocols
[protocol
].proto_name
; protocol
++)
2856 p
= smb_buf(inbuf
)+1;
2858 if (lp_maxprotocol() >= supported_protocols
[protocol
].protocol_level
)
2859 while (p
< (smb_buf(inbuf
) + bcc
))
2861 if (strequal(p
,supported_protocols
[protocol
].proto_name
))
2870 SSVAL(outbuf
,smb_vwv0
,choice
);
2872 extern fstring remote_proto
;
2873 strcpy(remote_proto
,supported_protocols
[protocol
].short_name
);
2874 reload_services(True
);
2875 outsize
= supported_protocols
[protocol
].proto_reply_fn(outbuf
);
2876 DEBUG(3,("Selected protocol %s\n",supported_protocols
[protocol
].proto_name
));
2879 DEBUG(0,("No protocol supported !\n"));
2881 SSVAL(outbuf
,smb_vwv0
,choice
);
2883 DEBUG(5,("%s negprot index=%d\n",timestring(),choice
));
2889 /****************************************************************************
2890 close all open files for a connection
2891 ****************************************************************************/
2892 static void close_open_files(int cnum
)
2895 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
2896 if( Files
[i
].cnum
== cnum
&& Files
[i
].open
) {
2903 /****************************************************************************
2905 ****************************************************************************/
2906 void close_cnum(int cnum
, uint16 vuid
)
2908 DirCacheFlush(SNUM(cnum
));
2912 if (!OPEN_CNUM(cnum
))
2914 DEBUG(0,("Can't close cnum %d\n",cnum
));
2918 DEBUG(IS_IPC(cnum
)?3:1,("%s %s (%s) closed connection to service %s\n",
2920 remote_machine
,client_addr(),
2921 lp_servicename(SNUM(cnum
))));
2923 yield_connection(cnum
,
2924 lp_servicename(SNUM(cnum
)),
2925 lp_max_connections(SNUM(cnum
)));
2927 if (lp_status(SNUM(cnum
)))
2928 yield_connection(cnum
,"STATUS.",MAXSTATUS
);
2930 close_open_files(cnum
);
2931 dptr_closecnum(cnum
);
2933 /* execute any "postexec = " line */
2934 if (*lp_postexec(SNUM(cnum
)) && become_user(cnum
,vuid
))
2937 strcpy(cmd
,lp_postexec(SNUM(cnum
)));
2938 standard_sub(cnum
,cmd
);
2939 smbrun(cmd
,NULL
,False
);
2944 /* execute any "root postexec = " line */
2945 if (*lp_rootpostexec(SNUM(cnum
)))
2948 strcpy(cmd
,lp_rootpostexec(SNUM(cnum
)));
2949 standard_sub(cnum
,cmd
);
2950 smbrun(cmd
,NULL
,False
);
2953 Connections
[cnum
].open
= False
;
2954 num_connections_open
--;
2955 if (Connections
[cnum
].ngroups
&& Connections
[cnum
].groups
)
2957 if (Connections
[cnum
].igroups
!= (int *)Connections
[cnum
].groups
)
2958 free(Connections
[cnum
].groups
);
2959 free(Connections
[cnum
].igroups
);
2960 Connections
[cnum
].groups
= NULL
;
2961 Connections
[cnum
].igroups
= NULL
;
2962 Connections
[cnum
].ngroups
= 0;
2965 string_set(&Connections
[cnum
].user
,"");
2966 string_set(&Connections
[cnum
].dirpath
,"");
2967 string_set(&Connections
[cnum
].connectpath
,"");
2971 /****************************************************************************
2972 simple routines to do connection counting
2973 ****************************************************************************/
2974 BOOL
yield_connection(int cnum
,char *name
,int max_connections
)
2976 struct connect_record crec
;
2979 int mypid
= getpid();
2982 DEBUG(3,("Yielding connection to %d %s\n",cnum
,name
));
2984 if (max_connections
<= 0)
2987 bzero(&crec
,sizeof(crec
));
2989 strcpy(fname
,lp_lockdir());
2990 standard_sub(cnum
,fname
);
2991 trim_string(fname
,"","/");
2995 strcat(fname
,".LCK");
2997 f
= fopen(fname
,"r+");
3000 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname
,strerror(errno
)));
3004 fseek(f
,0,SEEK_SET
);
3006 /* find a free spot */
3007 for (i
=0;i
<max_connections
;i
++)
3009 if (fread(&crec
,sizeof(crec
),1,f
) != 1)
3011 DEBUG(2,("Entry not found in lock file %s\n",fname
));
3015 if (crec
.pid
== mypid
&& crec
.cnum
== cnum
)
3019 if (crec
.pid
!= mypid
|| crec
.cnum
!= cnum
)
3022 DEBUG(2,("Entry not found in lock file %s\n",fname
));
3026 bzero((void *)&crec
,sizeof(crec
));
3028 /* remove our mark */
3029 if (fseek(f
,i
*sizeof(crec
),SEEK_SET
) != 0 ||
3030 fwrite(&crec
,sizeof(crec
),1,f
) != 1)
3032 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname
,strerror(errno
)));
3037 DEBUG(3,("Yield successful\n"));
3044 /****************************************************************************
3045 simple routines to do connection counting
3046 ****************************************************************************/
3047 BOOL
claim_connection(int cnum
,char *name
,int max_connections
,BOOL Clear
)
3049 struct connect_record crec
;
3052 int snum
= SNUM(cnum
);
3056 if (max_connections
<= 0)
3059 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name
,max_connections
));
3061 strcpy(fname
,lp_lockdir());
3062 standard_sub(cnum
,fname
);
3063 trim_string(fname
,"","/");
3065 if (!directory_exist(fname
,NULL
))
3070 strcat(fname
,".LCK");
3072 if (!file_exist(fname
,NULL
))
3074 int oldmask
= umask(022);
3075 f
= fopen(fname
,"w");
3080 total_recs
= file_size(fname
) / sizeof(crec
);
3082 f
= fopen(fname
,"r+");
3086 DEBUG(1,("couldn't open lock file %s\n",fname
));
3090 /* find a free spot */
3091 for (i
=0;i
<max_connections
;i
++)
3094 if (i
>=total_recs
||
3095 fseek(f
,i
*sizeof(crec
),SEEK_SET
) != 0 ||
3096 fread(&crec
,sizeof(crec
),1,f
) != 1)
3098 if (foundi
< 0) foundi
= i
;
3102 if (Clear
&& crec
.pid
&& !process_exists(crec
.pid
))
3104 fseek(f
,i
*sizeof(crec
),SEEK_SET
);
3105 bzero((void *)&crec
,sizeof(crec
));
3106 fwrite(&crec
,sizeof(crec
),1,f
);
3107 if (foundi
< 0) foundi
= i
;
3110 if (foundi
< 0 && (!crec
.pid
|| !process_exists(crec
.pid
)))
3119 DEBUG(3,("no free locks in %s\n",fname
));
3124 /* fill in the crec */
3125 bzero((void *)&crec
,sizeof(crec
));
3126 crec
.magic
= 0x280267;
3127 crec
.pid
= getpid();
3129 crec
.uid
= Connections
[cnum
].uid
;
3130 crec
.gid
= Connections
[cnum
].gid
;
3131 StrnCpy(crec
.name
,lp_servicename(snum
),sizeof(crec
.name
)-1);
3132 crec
.start
= time(NULL
);
3134 StrnCpy(crec
.machine
,remote_machine
,sizeof(crec
.machine
)-1);
3135 StrnCpy(crec
.addr
,client_addr(),sizeof(crec
.addr
)-1);
3138 if (fseek(f
,foundi
*sizeof(crec
),SEEK_SET
) != 0 ||
3139 fwrite(&crec
,sizeof(crec
),1,f
) != 1)
3150 /*******************************************************************
3151 prepare to dump a core file - carefully!
3152 ********************************************************************/
3153 static BOOL
dump_core(void)
3157 strcpy(dname
,debugf
);
3158 if ((p
=strrchr(dname
,'/'))) *p
=0;
3159 strcat(dname
,"/corefiles");
3161 sys_chown(dname
,getuid(),getgid());
3163 if (chdir(dname
)) return(False
);
3166 #ifndef NO_GETRLIMIT
3170 getrlimit(RLIMIT_CORE
, &rlp
);
3171 rlp
.rlim_cur
= MAX(4*1024*1024,rlp
.rlim_cur
);
3172 setrlimit(RLIMIT_CORE
, &rlp
);
3173 getrlimit(RLIMIT_CORE
, &rlp
);
3174 DEBUG(3,("Core limits now %d %d\n",rlp
.rlim_cur
,rlp
.rlim_max
));
3180 DEBUG(0,("Dumping core in %s\n",dname
));
3185 /****************************************************************************
3187 ****************************************************************************/
3188 void exit_server(char *reason
)
3190 static int firsttime
=1;
3193 if (!firsttime
) exit(0);
3197 DEBUG(2,("Closing connections\n"));
3198 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
3199 if (Connections
[i
].open
)
3202 if (dcelogin_atmost_once
)
3206 int oldlevel
= DEBUGLEVEL
;
3208 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message
)));
3210 show_msg(last_inbuf
);
3211 DEBUGLEVEL
= oldlevel
;
3212 DEBUG(0,("===============================================================\n"));
3214 if (dump_core()) return;
3218 #if FAST_SHARE_MODES
3219 stop_share_mode_mgmt();
3222 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason
?reason
:""));
3226 /****************************************************************************
3227 do some standard substitutions in a string
3228 ****************************************************************************/
3229 void standard_sub(int cnum
,char *s
)
3231 if (!strchr(s
,'%')) return;
3233 if (VALID_CNUM(cnum
))
3235 string_sub(s
,"%S",lp_servicename(Connections
[cnum
].service
));
3236 string_sub(s
,"%P",Connections
[cnum
].connectpath
);
3237 string_sub(s
,"%u",Connections
[cnum
].user
);
3238 if (strstr(s
,"%H")) {
3239 char *home
= get_home_dir(Connections
[cnum
].user
);
3240 if (home
) string_sub(s
,"%H",home
);
3242 string_sub(s
,"%g",gidtoname(Connections
[cnum
].gid
));
3244 standard_sub_basic(s
);
3248 These flags determine some of the permissions required to do an operation
3250 Note that I don't set NEED_WRITE on some write operations because they
3251 are used by some brain-dead clients when printing, and I don't want to
3252 force write permissions on print services.
3254 #define AS_USER (1<<0)
3255 #define NEED_WRITE (1<<1)
3256 #define TIME_INIT (1<<2)
3257 #define CAN_IPC (1<<3)
3258 #define AS_GUEST (1<<5)
3262 define a list of possible SMB messages and their corresponding
3263 functions. Any message that has a NULL function is unimplemented -
3264 please feel free to contribute implementations!
3266 struct smb_message_struct
3280 {SMBnegprot
,"SMBnegprot",reply_negprot
,0},
3281 {SMBtcon
,"SMBtcon",reply_tcon
,0},
3282 {SMBtdis
,"SMBtdis",reply_tdis
,0},
3283 {SMBexit
,"SMBexit",reply_exit
,0},
3284 {SMBioctl
,"SMBioctl",reply_ioctl
,0},
3285 {SMBecho
,"SMBecho",reply_echo
,0},
3286 {SMBsesssetupX
,"SMBsesssetupX",reply_sesssetup_and_X
,0},
3287 {SMBtconX
,"SMBtconX",reply_tcon_and_X
,0},
3288 {SMBulogoffX
, "SMBulogoffX", reply_ulogoffX
, 0}, /* ulogoff doesn't give a valid TID */
3289 {SMBgetatr
,"SMBgetatr",reply_getatr
,AS_USER
},
3290 {SMBsetatr
,"SMBsetatr",reply_setatr
,AS_USER
| NEED_WRITE
},
3291 {SMBchkpth
,"SMBchkpth",reply_chkpth
,AS_USER
},
3292 {SMBsearch
,"SMBsearch",reply_search
,AS_USER
},
3293 {SMBopen
,"SMBopen",reply_open
,AS_USER
},
3295 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3296 {SMBcreate
,"SMBcreate",reply_mknew
,AS_USER
},
3297 {SMBmknew
,"SMBmknew",reply_mknew
,AS_USER
},
3299 {SMBunlink
,"SMBunlink",reply_unlink
,AS_USER
| NEED_WRITE
},
3300 {SMBread
,"SMBread",reply_read
,AS_USER
},
3301 {SMBwrite
,"SMBwrite",reply_write
,AS_USER
},
3302 {SMBclose
,"SMBclose",reply_close
,AS_USER
| CAN_IPC
},
3303 {SMBmkdir
,"SMBmkdir",reply_mkdir
,AS_USER
| NEED_WRITE
},
3304 {SMBrmdir
,"SMBrmdir",reply_rmdir
,AS_USER
| NEED_WRITE
},
3305 {SMBdskattr
,"SMBdskattr",reply_dskattr
,AS_USER
},
3306 {SMBmv
,"SMBmv",reply_mv
,AS_USER
| NEED_WRITE
},
3308 /* this is a Pathworks specific call, allowing the
3309 changing of the root path */
3310 {pSETDIR
,"pSETDIR",reply_setdir
,AS_USER
},
3312 {SMBlseek
,"SMBlseek",reply_lseek
,AS_USER
},
3313 {SMBflush
,"SMBflush",reply_flush
,AS_USER
},
3314 {SMBctemp
,"SMBctemp",reply_ctemp
,AS_USER
},
3315 {SMBsplopen
,"SMBsplopen",reply_printopen
,AS_USER
},
3316 {SMBsplclose
,"SMBsplclose",reply_printclose
,AS_USER
},
3317 {SMBsplretq
,"SMBsplretq",reply_printqueue
,AS_USER
|AS_GUEST
},
3318 {SMBsplwr
,"SMBsplwr",reply_printwrite
,AS_USER
},
3319 {SMBlock
,"SMBlock",reply_lock
,AS_USER
},
3320 {SMBunlock
,"SMBunlock",reply_unlock
,AS_USER
},
3322 /* CORE+ PROTOCOL FOLLOWS */
3324 {SMBreadbraw
,"SMBreadbraw",reply_readbraw
,AS_USER
},
3325 {SMBwritebraw
,"SMBwritebraw",reply_writebraw
,AS_USER
},
3326 {SMBwriteclose
,"SMBwriteclose",reply_writeclose
,AS_USER
},
3327 {SMBlockread
,"SMBlockread",reply_lockread
,AS_USER
},
3328 {SMBwriteunlock
,"SMBwriteunlock",reply_writeunlock
,AS_USER
},
3330 /* LANMAN1.0 PROTOCOL FOLLOWS */
3332 {SMBreadBmpx
,"SMBreadBmpx",reply_readbmpx
,AS_USER
},
3333 {SMBreadBs
,"SMBreadBs",NULL
,AS_USER
},
3334 {SMBwriteBmpx
,"SMBwriteBmpx",reply_writebmpx
,AS_USER
},
3335 {SMBwriteBs
,"SMBwriteBs",reply_writebs
,AS_USER
},
3336 {SMBwritec
,"SMBwritec",NULL
,AS_USER
},
3337 {SMBsetattrE
,"SMBsetattrE",reply_setattrE
,AS_USER
| NEED_WRITE
},
3338 {SMBgetattrE
,"SMBgetattrE",reply_getattrE
,AS_USER
},
3339 {SMBtrans
,"SMBtrans",reply_trans
,AS_USER
| CAN_IPC
},
3340 {SMBtranss
,"SMBtranss",NULL
,AS_USER
| CAN_IPC
},
3341 {SMBioctls
,"SMBioctls",NULL
,AS_USER
},
3342 {SMBcopy
,"SMBcopy",reply_copy
,AS_USER
| NEED_WRITE
},
3343 {SMBmove
,"SMBmove",NULL
,AS_USER
| NEED_WRITE
},
3345 {SMBopenX
,"SMBopenX",reply_open_and_X
,AS_USER
| CAN_IPC
},
3346 {SMBreadX
,"SMBreadX",reply_read_and_X
,AS_USER
},
3347 {SMBwriteX
,"SMBwriteX",reply_write_and_X
,AS_USER
},
3348 {SMBlockingX
,"SMBlockingX",reply_lockingX
,AS_USER
},
3350 {SMBffirst
,"SMBffirst",reply_search
,AS_USER
},
3351 {SMBfunique
,"SMBfunique",reply_search
,AS_USER
},
3352 {SMBfclose
,"SMBfclose",reply_fclose
,AS_USER
},
3354 /* LANMAN2.0 PROTOCOL FOLLOWS */
3355 {SMBfindnclose
, "SMBfindnclose", reply_findnclose
, AS_USER
},
3356 {SMBfindclose
, "SMBfindclose", reply_findclose
,AS_USER
},
3357 {SMBtrans2
, "SMBtrans2", reply_trans2
, AS_USER
},
3358 {SMBtranss2
, "SMBtranss2", reply_transs2
, AS_USER
},
3360 /* messaging routines */
3361 {SMBsends
,"SMBsends",reply_sends
,AS_GUEST
},
3362 {SMBsendstrt
,"SMBsendstrt",reply_sendstrt
,AS_GUEST
},
3363 {SMBsendend
,"SMBsendend",reply_sendend
,AS_GUEST
},
3364 {SMBsendtxt
,"SMBsendtxt",reply_sendtxt
,AS_GUEST
},
3366 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3368 {SMBsendb
,"SMBsendb",NULL
,AS_GUEST
},
3369 {SMBfwdname
,"SMBfwdname",NULL
,AS_GUEST
},
3370 {SMBcancelf
,"SMBcancelf",NULL
,AS_GUEST
},
3371 {SMBgetmac
,"SMBgetmac",NULL
,AS_GUEST
}
3374 /****************************************************************************
3375 return a string containing the function name of a SMB command
3376 ****************************************************************************/
3377 char *smb_fn_name(int type
)
3379 static char *unknown_name
= "SMBunknown";
3380 static int num_smb_messages
=
3381 sizeof(smb_messages
) / sizeof(struct smb_message_struct
);
3384 for (match
=0;match
<num_smb_messages
;match
++)
3385 if (smb_messages
[match
].code
== type
)
3388 if (match
== num_smb_messages
)
3389 return(unknown_name
);
3391 return(smb_messages
[match
].name
);
3395 /****************************************************************************
3396 do a switch on the message type, and return the response size
3397 ****************************************************************************/
3398 static int switch_message(int type
,char *inbuf
,char *outbuf
,int size
,int bufsize
)
3402 static int num_smb_messages
=
3403 sizeof(smb_messages
) / sizeof(struct smb_message_struct
);
3407 struct timeval msg_start_time
;
3408 struct timeval msg_end_time
;
3409 static unsigned long total_time
= 0;
3411 GetTimeOfDay(&msg_start_time
);
3418 last_message
= type
;
3420 /* make sure this is an SMB packet */
3421 if (strncmp(smb_base(inbuf
),"\377SMB",4) != 0)
3423 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf
)));
3427 for (match
=0;match
<num_smb_messages
;match
++)
3428 if (smb_messages
[match
].code
== type
)
3431 if (match
== num_smb_messages
)
3433 DEBUG(0,("Unknown message type %d!\n",type
));
3434 outsize
= reply_unknown(inbuf
,outbuf
);
3438 DEBUG(3,("switch message %s (pid %d)\n",smb_messages
[match
].name
,pid
));
3439 if (smb_messages
[match
].fn
)
3441 int cnum
= SVAL(inbuf
,smb_tid
);
3442 int flags
= smb_messages
[match
].flags
;
3443 uint16 session_tag
= SVAL(inbuf
,smb_uid
);
3445 /* does this protocol need to be run as root? */
3446 if (!(flags
& AS_USER
))
3449 /* does this protocol need to be run as the connected user? */
3450 if ((flags
& AS_USER
) && !become_user(cnum
,session_tag
)) {
3451 if (flags
& AS_GUEST
)
3454 return(ERROR(ERRSRV
,ERRinvnid
));
3456 /* this code is to work around a bug is MS client 3 without
3457 introducing a security hole - it needs to be able to do
3458 print queue checks as guest if it isn't logged in properly */
3459 if (flags
& AS_USER
)
3462 /* does it need write permission? */
3463 if ((flags
& NEED_WRITE
) && !CAN_WRITE(cnum
))
3464 return(ERROR(ERRSRV
,ERRaccess
));
3466 /* ipc services are limited */
3467 if (IS_IPC(cnum
) && (flags
& AS_USER
) && !(flags
& CAN_IPC
))
3468 return(ERROR(ERRSRV
,ERRaccess
));
3470 /* load service specific parameters */
3471 if (OPEN_CNUM(cnum
) && !become_service(cnum
,(flags
& AS_USER
)?True
:False
))
3472 return(ERROR(ERRSRV
,ERRaccess
));
3474 /* does this protocol need to be run as guest? */
3475 if ((flags
& AS_GUEST
) && (!become_guest() || !check_access(-1)))
3476 return(ERROR(ERRSRV
,ERRaccess
));
3480 outsize
= smb_messages
[match
].fn(inbuf
,outbuf
,size
,bufsize
);
3484 outsize
= reply_unknown(inbuf
,outbuf
);
3489 GetTimeOfDay(&msg_end_time
);
3490 if (!(smb_messages
[match
].flags
& TIME_INIT
))
3492 smb_messages
[match
].time
= 0;
3493 smb_messages
[match
].flags
|= TIME_INIT
;
3496 unsigned long this_time
=
3497 (msg_end_time
.tv_sec
- msg_start_time
.tv_sec
)*1e6
+
3498 (msg_end_time
.tv_usec
- msg_start_time
.tv_usec
);
3499 smb_messages
[match
].time
+= this_time
;
3500 total_time
+= this_time
;
3502 DEBUG(2,("TIME %s %d usecs %g pct\n",
3503 smb_fn_name(type
),smb_messages
[match
].time
,
3504 (100.0*smb_messages
[match
].time
) / total_time
));
3511 /****************************************************************************
3512 construct a chained reply and add it to the already made reply
3513 **************************************************************************/
3514 int chain_reply(char *inbuf
,char *outbuf
,int size
,int bufsize
)
3516 static char *orig_inbuf
;
3517 static char *orig_outbuf
;
3518 int smb_com1
, smb_com2
= CVAL(inbuf
,smb_vwv0
);
3519 unsigned smb_off2
= SVAL(inbuf
,smb_vwv1
);
3520 char *inbuf2
, *outbuf2
;
3522 char inbuf_saved
[smb_wct
];
3523 char outbuf_saved
[smb_wct
];
3524 extern int chain_size
;
3525 int wct
= CVAL(outbuf
,smb_wct
);
3526 int outsize
= smb_size
+ 2*wct
+ SVAL(outbuf
,smb_vwv0
+2*wct
);
3528 /* maybe its not chained */
3529 if (smb_com2
== 0xFF) {
3530 CVAL(outbuf
,smb_vwv0
) = 0xFF;
3534 if (chain_size
== 0) {
3535 /* this is the first part of the chain */
3537 orig_outbuf
= outbuf
;
3540 /* we need to tell the client where the next part of the reply will be */
3541 SSVAL(outbuf
,smb_vwv1
,smb_offset(outbuf
+outsize
,outbuf
));
3542 CVAL(outbuf
,smb_vwv0
) = smb_com2
;
3544 /* remember how much the caller added to the chain, only counting stuff
3545 after the parameter words */
3546 chain_size
+= outsize
- smb_wct
;
3548 /* work out pointers into the original packets. The
3549 headers on these need to be filled in */
3550 inbuf2
= orig_inbuf
+ smb_off2
+ 4 - smb_wct
;
3551 outbuf2
= orig_outbuf
+ SVAL(outbuf
,smb_vwv1
) + 4 - smb_wct
;
3553 /* remember the original command type */
3554 smb_com1
= CVAL(orig_inbuf
,smb_com
);
3556 /* save the data which will be overwritten by the new headers */
3557 memcpy(inbuf_saved
,inbuf2
,smb_wct
);
3558 memcpy(outbuf_saved
,outbuf2
,smb_wct
);
3560 /* give the new packet the same header as the last part of the SMB */
3561 memmove(inbuf2
,inbuf
,smb_wct
);
3563 /* create the in buffer */
3564 CVAL(inbuf2
,smb_com
) = smb_com2
;
3566 /* create the out buffer */
3567 bzero(outbuf2
,smb_size
);
3568 set_message(outbuf2
,0,0,True
);
3569 CVAL(outbuf2
,smb_com
) = CVAL(inbuf2
,smb_com
);
3571 memcpy(outbuf2
+4,inbuf2
+4,4);
3572 CVAL(outbuf2
,smb_rcls
) = SUCCESS
;
3573 CVAL(outbuf2
,smb_reh
) = 0;
3574 CVAL(outbuf2
,smb_flg
) = 0x80 | (CVAL(inbuf2
,smb_flg
) & 0x8); /* bit 7 set
3576 SSVAL(outbuf2
,smb_flg2
,1); /* say we support long filenames */
3577 SSVAL(outbuf2
,smb_err
,SUCCESS
);
3578 SSVAL(outbuf2
,smb_tid
,SVAL(inbuf2
,smb_tid
));
3579 SSVAL(outbuf2
,smb_pid
,SVAL(inbuf2
,smb_pid
));
3580 SSVAL(outbuf2
,smb_uid
,SVAL(inbuf2
,smb_uid
));
3581 SSVAL(outbuf2
,smb_mid
,SVAL(inbuf2
,smb_mid
));
3583 DEBUG(3,("Chained message\n"));
3586 /* process the request */
3587 outsize2
= switch_message(smb_com2
,inbuf2
,outbuf2
,size
-chain_size
,
3588 bufsize
-chain_size
);
3590 /* copy the new reply and request headers over the old ones, but
3591 preserve the smb_com field */
3592 memmove(orig_outbuf
,outbuf2
,smb_wct
);
3593 CVAL(orig_outbuf
,smb_com
) = smb_com1
;
3595 /* restore the saved data, being careful not to overwrite any
3596 data from the reply header */
3597 memcpy(inbuf2
,inbuf_saved
,smb_wct
);
3599 int ofs
= smb_wct
- PTR_DIFF(outbuf2
,orig_outbuf
);
3600 if (ofs
< 0) ofs
= 0;
3601 memmove(outbuf2
+ofs
,outbuf_saved
+ofs
,smb_wct
-ofs
);
3609 /****************************************************************************
3610 construct a reply to the incoming packet
3611 ****************************************************************************/
3612 int construct_reply(char *inbuf
,char *outbuf
,int size
,int bufsize
)
3614 int type
= CVAL(inbuf
,smb_com
);
3616 int msg_type
= CVAL(inbuf
,0);
3617 extern int chain_size
;
3619 smb_last_time
= time(NULL
);
3624 bzero(outbuf
,smb_size
);
3627 return(reply_special(inbuf
,outbuf
));
3629 CVAL(outbuf
,smb_com
) = CVAL(inbuf
,smb_com
);
3630 set_message(outbuf
,0,0,True
);
3632 memcpy(outbuf
+4,inbuf
+4,4);
3633 CVAL(outbuf
,smb_rcls
) = SUCCESS
;
3634 CVAL(outbuf
,smb_reh
) = 0;
3635 CVAL(outbuf
,smb_flg
) = 0x80 | (CVAL(inbuf
,smb_flg
) & 0x8); /* bit 7 set
3637 SSVAL(outbuf
,smb_flg2
,1); /* say we support long filenames */
3638 SSVAL(outbuf
,smb_err
,SUCCESS
);
3639 SSVAL(outbuf
,smb_tid
,SVAL(inbuf
,smb_tid
));
3640 SSVAL(outbuf
,smb_pid
,SVAL(inbuf
,smb_pid
));
3641 SSVAL(outbuf
,smb_uid
,SVAL(inbuf
,smb_uid
));
3642 SSVAL(outbuf
,smb_mid
,SVAL(inbuf
,smb_mid
));
3644 outsize
= switch_message(type
,inbuf
,outbuf
,size
,bufsize
);
3646 outsize
+= chain_size
;
3649 smb_setlen(outbuf
,outsize
- 4);
3654 /****************************************************************************
3655 process commands from the client
3656 ****************************************************************************/
3657 static void process(void)
3659 static int trans_num
= 0;
3663 InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3664 OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3665 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
3668 InBuffer
+= SMB_ALIGNMENT
;
3669 OutBuffer
+= SMB_ALIGNMENT
;
3672 DEBUG(3,("priming nmbd\n"));
3675 ip
= *interpret_addr2("localhost");
3676 if (zero_ip(ip
)) ip
= *interpret_addr2("127.0.0.1");
3678 send_one_packet(OutBuffer
,1,ip
,NMB_PORT
,SOCK_DGRAM
);
3688 int deadtime
= lp_deadtime()*60;
3690 int last_keepalive
=0;
3693 deadtime
= DEFAULT_SMBD_TIMEOUT
;
3695 if (lp_readprediction())
3696 do_read_prediction();
3699 extern pstring share_del_pending
;
3700 if (*share_del_pending
) {
3702 if (!unlink(share_del_pending
))
3703 DEBUG(3,("Share file deleted %s\n",share_del_pending
));
3705 DEBUG(2,("Share del failed of %s\n",share_del_pending
));
3706 share_del_pending
[0] = 0;
3710 if (share_mode_pending
) {
3712 check_share_modes();
3713 share_mode_pending
=False
;
3718 for (counter
=SMBD_SELECT_LOOP
;
3719 !receive_smb(Client
,InBuffer
,SMBD_SELECT_LOOP
*1000);
3720 counter
+= SMBD_SELECT_LOOP
)
3724 BOOL allidle
= True
;
3725 extern int keepalive
;
3727 if (smb_read_error
== READ_EOF
) {
3728 DEBUG(3,("end of file from client\n"));
3732 if (smb_read_error
== READ_ERROR
) {
3733 DEBUG(3,("receive_smb error (%s) exiting\n",
3740 /* become root again if waiting */
3743 /* check for smb.conf reload */
3744 if (!(counter
%SMBD_RELOAD_CHECK
))
3745 reload_services(True
);
3747 /* check the share modes every 10 secs */
3748 if (!(counter
%SHARE_MODES_CHECK
))
3749 check_share_modes();
3751 /* clean the share modes every 5 minutes */
3752 if (!(counter
%SHARE_MODES_CLEAN
))
3753 clean_share_modes();
3755 /* automatic timeout if all connections are closed */
3756 if (num_connections_open
==0 && counter
>= IDLE_CLOSED_TIMEOUT
) {
3757 DEBUG(2,("%s Closing idle connection\n",timestring()));
3761 if (keepalive
&& (counter
-last_keepalive
)>keepalive
) {
3762 extern int password_client
;
3763 if (!send_keepalive(Client
)) {
3764 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3767 /* also send a keepalive to the password server if its still
3769 if (password_client
!= -1)
3770 send_keepalive(password_client
);
3771 last_keepalive
= counter
;
3774 /* check for connection timeouts */
3775 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
3776 if (Connections
[i
].open
)
3778 /* close dirptrs on connections that are idle */
3779 if ((t
-Connections
[i
].lastused
)>DPTR_IDLE_TIMEOUT
)
3782 if (Connections
[i
].num_files_open
> 0 ||
3783 (t
-Connections
[i
].lastused
)<deadtime
)
3787 if (allidle
&& num_connections_open
>0) {
3788 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3793 msg_type
= CVAL(InBuffer
,0);
3794 msg_flags
= CVAL(InBuffer
,1);
3795 type
= CVAL(InBuffer
,smb_com
);
3797 len
= smb_len(InBuffer
);
3799 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type
,len
));
3803 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num
,nread
));
3806 if(trans_num
== 1 && VT_Check(InBuffer
)) {
3816 nread
= construct_reply(InBuffer
,OutBuffer
,nread
,maxxmit
);
3819 if (CVAL(OutBuffer
,0) == 0)
3820 show_msg(OutBuffer
);
3822 if (nread
!= smb_len(OutBuffer
) + 4)
3824 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3826 smb_len(OutBuffer
)));
3829 send_smb(Client
,OutBuffer
);
3836 /****************************************************************************
3837 initialise connect, service and file structs
3838 ****************************************************************************/
3839 static void init_structs(void )
3842 get_myname(myhostname
,NULL
);
3844 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
3846 Connections
[i
].open
= False
;
3847 Connections
[i
].num_files_open
=0;
3848 Connections
[i
].lastused
=0;
3849 Connections
[i
].used
=False
;
3850 string_init(&Connections
[i
].user
,"");
3851 string_init(&Connections
[i
].dirpath
,"");
3852 string_init(&Connections
[i
].connectpath
,"");
3853 string_init(&Connections
[i
].origpath
,"");
3856 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
3858 Files
[i
].open
= False
;
3859 string_init(&Files
[i
].name
,"");
3863 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
3865 file_fd_struct
*fd_ptr
= &FileFd
[i
];
3866 fd_ptr
->ref_count
= 0;
3867 fd_ptr
->dev
= (int32
)-1;
3868 fd_ptr
->inode
= (int32
)-1;
3870 fd_ptr
->fd_readonly
= -1;
3871 fd_ptr
->fd_writeonly
= -1;
3872 fd_ptr
->real_open_flags
= -1;
3878 /****************************************************************************
3879 usage on the program
3880 ****************************************************************************/
3881 static void usage(char *pname
)
3883 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3885 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname
);
3886 printf("Version %s\n",VERSION
);
3887 printf("\t-D become a daemon\n");
3888 printf("\t-p port listen on the specified port\n");
3889 printf("\t-d debuglevel set the debuglevel\n");
3890 printf("\t-l log basename. Basename for log/debug files\n");
3891 printf("\t-s services file. Filename of services file\n");
3892 printf("\t-P passive only\n");
3893 printf("\t-a overwrite log file, don't append\n");
3898 /****************************************************************************
3900 ****************************************************************************/
3901 int main(int argc
,char *argv
[])
3903 extern BOOL append_log
;
3904 /* shall I run as a daemon */
3905 BOOL is_daemon
= False
;
3906 int port
= SMB_PORT
;
3908 extern char *optarg
;
3909 char pidFile
[100] = { 0 };
3911 #ifdef NEED_AUTH_PARAMETERS
3912 set_auth_parameters(argc
,argv
);
3923 strcpy(debugf
,SMBLOGFILE
);
3925 setup_logging(argv
[0],False
);
3927 charset_initialise();
3929 /* make absolutely sure we run as root - to handle cases whre people
3930 are crazy enough to have it setuid */
3940 fault_setup(exit_server
);
3941 signal(SIGTERM
, SIGNAL_CAST dflt_sig
);
3943 /* we want total control over the permissions on created files,
3944 so set our umask to 0 */
3951 /* this is for people who can't start the program correctly */
3952 while (argc
> 1 && (*argv
[1] != '-'))
3958 while ((opt
= getopt(argc
, argv
, "O:i:l:s:d:Dp:hPaf:")) != EOF
)
3962 strncpy(pidFile
, optarg
, sizeof(pidFile
));
3965 strcpy(user_socket_options
,optarg
);
3968 strcpy(scope
,optarg
);
3972 extern BOOL passive
;
3977 strcpy(servicesf
,optarg
);
3980 strcpy(debugf
,optarg
);
3984 extern BOOL append_log
;
3985 append_log
= !append_log
;
3995 DEBUGLEVEL
= atoi(optarg
);
3998 port
= atoi(optarg
);
4011 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION
));
4012 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4014 #ifndef NO_GETRLIMIT
4015 #ifdef RLIMIT_NOFILE
4018 getrlimit(RLIMIT_NOFILE
, &rlp
);
4019 rlp
.rlim_cur
= (MAX_OPEN_FILES
>rlp
.rlim_max
)? rlp
.rlim_max
:MAX_OPEN_FILES
;
4020 setrlimit(RLIMIT_NOFILE
, &rlp
);
4021 getrlimit(RLIMIT_NOFILE
, &rlp
);
4022 DEBUG(3,("Maximum number of open files per session is %d\n",rlp
.rlim_cur
));
4028 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4029 getuid(),getgid(),geteuid(),getegid()));
4031 if (sizeof(uint16
) < 2 || sizeof(uint32
) < 4)
4033 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4039 if (!reload_services(False
))
4042 #ifndef NO_SIGNAL_TEST
4043 signal(SIGHUP
,SIGNAL_CAST sig_hup
);
4046 DEBUG(3,("%s loaded services\n",timestring()));
4048 if (!is_daemon
&& !is_a_socket(0))
4050 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4056 DEBUG(3,("%s becoming a daemon\n",timestring()));
4065 if ((fd
= open(pidFile
,
4066 O_NONBLOCK
| O_CREAT
| O_WRONLY
| O_TRUNC
, 0644)) < 0)
4068 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile
, strerror(errno
)));
4071 if(fcntl_lock(fd
,F_SETLK
,0,1,F_WRLCK
)==False
)
4073 DEBUG(0,("ERROR: smbd is already running\n"));
4076 sprintf(buf
, "%u\n", (unsigned int) getpid());
4077 if (write(fd
, buf
, strlen(buf
)) < 0)
4079 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile
, strerror(errno
)));
4082 /* Leave pid file open & locked for the duration... */
4085 if (!open_sockets(is_daemon
,port
))
4088 #if FAST_SHARE_MODES
4089 if (!start_share_mode_mgmt())
4093 /* possibly reload the services file. */
4094 reload_services(True
);
4096 maxxmit
= MIN(lp_maxxmit(),BUFFER_SIZE
);
4100 if (sys_chroot(lp_rootdir()) == 0)
4101 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4107 exit_server("normal exit");