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
);
136 if (MAP_ARCHIVE(cnum
) && IS_DOS_ARCHIVE(dosmode
))
139 if (MAP_SYSTEM(cnum
) && IS_DOS_SYSTEM(dosmode
))
142 if (MAP_HIDDEN(cnum
) && IS_DOS_HIDDEN(dosmode
))
145 result
&= CREATE_MODE(cnum
);
150 /****************************************************************************
151 change a unix mode to a dos mode
152 ****************************************************************************/
153 int dos_mode(int cnum
,char *path
,struct stat
*sbuf
)
156 extern struct current_user current_user
;
158 if (CAN_WRITE(cnum
) && !lp_alternate_permissions(SNUM(cnum
))) {
159 if (!((sbuf
->st_mode
& S_IWOTH
) ||
160 Connections
[cnum
].admin_user
||
161 ((sbuf
->st_mode
& S_IWUSR
) && current_user
.uid
==sbuf
->st_uid
) ||
162 ((sbuf
->st_mode
& S_IWGRP
) &&
163 in_group(sbuf
->st_gid
,current_user
.gid
,
164 current_user
.ngroups
,current_user
.igroups
))))
167 if ((sbuf
->st_mode
& S_IWUSR
) == 0)
171 if ((sbuf
->st_mode
& S_IXUSR
) != 0)
174 if (MAP_SYSTEM(cnum
) && ((sbuf
->st_mode
& S_IXGRP
) != 0))
177 if (MAP_HIDDEN(cnum
) && ((sbuf
->st_mode
& S_IXOTH
) != 0))
180 if (S_ISDIR(sbuf
->st_mode
))
181 result
= aDIR
| (result
& aRONLY
);
184 if (S_ISLNK(sbuf
->st_mode
) && S_ISDIR(sbuf
->st_mode
))
188 /* hide files with a name starting with a . */
189 if (lp_hide_dot_files(SNUM(cnum
)))
191 char *p
= strrchr(path
,'/');
197 if (p
[0] == '.' && p
[1] != '.' && p
[1] != 0)
205 /*******************************************************************
206 chmod a file - but preserve some bits
207 ********************************************************************/
208 int dos_chmod(int cnum
,char *fname
,int dosmode
,struct stat
*st
)
217 if (sys_stat(fname
,st
)) return(-1);
220 if (S_ISDIR(st
->st_mode
)) dosmode
|= aDIR
;
222 if (dos_mode(cnum
,fname
,st
) == dosmode
) return(0);
224 unixmode
= unix_mode(cnum
,dosmode
);
226 /* preserve the s bits */
227 mask
|= (S_ISUID
| S_ISGID
);
229 /* preserve the t bit */
234 /* possibly preserve the x bits */
235 if (!MAP_ARCHIVE(cnum
)) mask
|= S_IXUSR
;
236 if (!MAP_SYSTEM(cnum
)) mask
|= S_IXGRP
;
237 if (!MAP_HIDDEN(cnum
)) mask
|= S_IXOTH
;
239 unixmode
|= (st
->st_mode
& mask
);
241 /* if we previously had any r bits set then leave them alone */
242 if ((tmp
= st
->st_mode
& (S_IRUSR
|S_IRGRP
|S_IROTH
))) {
243 unixmode
&= ~(S_IRUSR
|S_IRGRP
|S_IROTH
);
247 /* if we previously had any w bits set then leave them alone
248 if the new mode is not rdonly */
249 if (!IS_DOS_READONLY(dosmode
) &&
250 (tmp
= st
->st_mode
& (S_IWUSR
|S_IWGRP
|S_IWOTH
))) {
251 unixmode
&= ~(S_IWUSR
|S_IWGRP
|S_IWOTH
);
255 return(sys_chmod(fname
,unixmode
));
259 /****************************************************************************
260 check if two filenames are equal
262 this needs to be careful about whether we are case sensitive
263 ****************************************************************************/
264 static BOOL
fname_equal(char *name1
, char *name2
)
266 int l1
= strlen(name1
);
267 int l2
= strlen(name2
);
269 /* handle filenames ending in a single dot */
270 if (l1
-l2
== 1 && name1
[l1
-1] == '.' && lp_strip_dot())
274 ret
= fname_equal(name1
,name2
);
279 if (l2
-l1
== 1 && name2
[l2
-1] == '.' && lp_strip_dot())
283 ret
= fname_equal(name1
,name2
);
288 /* now normal filename handling */
290 return(strcmp(name1
,name2
) == 0);
292 return(strequal(name1
,name2
));
296 /****************************************************************************
297 mangle the 2nd name and check if it is then equal to the first name
298 ****************************************************************************/
299 static BOOL
mangled_equal(char *name1
, char *name2
)
306 strcpy(tmpname
,name2
);
307 mangle_name_83(tmpname
);
309 return(strequal(name1
,tmpname
));
313 /****************************************************************************
314 scan a directory to find a filename, matching without case sensitivity
316 If the name looks like a mangled name then try via the mangling functions
317 ****************************************************************************/
318 static BOOL
scan_directory(char *path
, char *name
,int snum
,BOOL docache
)
325 mangled
= is_mangled(name
);
327 /* handle null paths */
331 if (docache
&& (dname
= DirCacheCheck(path
,name
,snum
))) {
337 check_mangled_stack(name
);
339 /* open the directory */
340 if (!(cur_dir
= OpenDir(path
)))
342 DEBUG(3,("scan dir didn't open dir [%s]\n",path
));
346 /* now scan for matching names */
347 while ((dname
= ReadDirName(cur_dir
)))
350 (strequal(dname
,".") || strequal(dname
,"..")))
354 if (!name_map_mangle(name2
,False
,snum
)) continue;
356 if ((mangled
&& mangled_equal(name
,name2
))
357 || fname_equal(name
, name2
))
359 /* we've found the file, change it's name and return */
360 if (docache
) DirCacheAdd(path
,name
,dname
,snum
);
371 /****************************************************************************
372 This routine is called to convert names from the dos namespace to unix
373 namespace. It needs to handle any case conversions, mangling, format
376 We assume that we have already done a chdir() to the right "root" directory
379 The function will return False if some part of the name except for the last
380 part cannot be resolved
382 If the saved_last_component != 0, then the unmodified last component
383 of the pathname is returned there. This is used in an exceptional
384 case in reply_mv (so far). If saved_last_component == 0 then nothing
386 ****************************************************************************/
387 BOOL
unix_convert(char *name
,int cnum
,pstring saved_last_component
)
394 if(saved_last_component
)
395 *saved_last_component
= 0;
397 /* convert to basic unix format - removing \ chars and cleaning it up */
399 unix_clean_name(name
);
401 if (!case_sensitive
&&
402 (!case_preserve
|| (is_8_3(name
) && !short_case_preserve
)))
405 /* names must be relative to the root of the service - trim any leading /.
406 also trim trailing /'s */
407 trim_string(name
,"/","/");
409 /* check if it's a printer file */
410 if (Connections
[cnum
].printer
)
412 if ((! *name
) || strchr(name
,'/') || !is_8_3(name
))
416 sprintf(name2
,"%.6s.XXXXXX",remote_machine
);
417 /* sanitise the name */
418 for (s
=name2
; *s
; s
++)
419 if (!issafe(*s
)) *s
= '_';
420 strcpy(name
,(char *)mktemp(name2
));
426 * Ensure saved_last_component is valid even if file exists.
428 if(saved_last_component
) {
429 end
= strrchr(name
, '/');
431 strcpy(saved_last_component
, end
+ 1);
433 strcpy(saved_last_component
, name
);
436 /* stat the name - if it exists then we are all done! */
437 if (sys_stat(name
,&st
) == 0)
440 DEBUG(5,("unix_convert(%s,%d)\n",name
,cnum
));
442 /* a special case - if we don't have any mangling chars and are case
443 sensitive then searching won't help */
444 if (case_sensitive
&& !is_mangled(name
) &&
445 !lp_strip_dot() && !use_mangled_map
)
448 /* now we need to recursively match the name against the real
449 directory structure */
452 while (strncmp(start
,"./",2) == 0)
455 /* now match each part of the path name separately, trying the names
456 as is first, then trying to scan the directory for matching names */
457 for (;start
;start
= (end
?end
+1:(char *)NULL
))
459 /* pinpoint the end of this section of the filename */
460 end
= strchr(start
, '/');
462 /* chop the name at this point */
465 if(saved_last_component
!= 0)
466 strcpy(saved_last_component
, end
? end
+ 1 : start
);
468 /* check if the name exists up to this point */
469 if (sys_stat(name
, &st
) == 0)
471 /* it exists. it must either be a directory or this must be
472 the last part of the path for it to be OK */
473 if (end
&& !(st
.st_mode
& S_IFDIR
))
475 /* an intermediate part of the name isn't a directory */
476 DEBUG(5,("Not a dir %s\n",start
));
487 /* remember the rest of the pathname so it can be restored
489 if (end
) strcpy(rest
,end
+1);
491 /* try to find this part of the path in the directory */
492 if (strchr(start
,'?') || strchr(start
,'*') ||
493 !scan_directory(dirpath
, start
, SNUM(cnum
), end
?True
:False
))
497 /* an intermediate part of the name can't be found */
498 DEBUG(5,("Intermediate not found %s\n",start
));
503 /* just the last part of the name doesn't exist */
504 /* we may need to strupper() or strlower() it in case
505 this conversion is being used for file creation
507 /* if the filename is of mixed case then don't normalise it */
508 if (!case_preserve
&&
509 (!strhasupper(start
) || !strhaslower(start
)))
512 /* check on the mangled stack to see if we can recover the
513 base of the filename */
514 if (is_mangled(start
))
515 check_mangled_stack(start
);
517 DEBUG(5,("New file %s\n",start
));
521 /* restore the rest of the string */
524 strcpy(start
+strlen(start
)+1,rest
);
525 end
= start
+ strlen(start
);
529 /* add to the dirpath that we have resolved so far */
530 if (*dirpath
) strcat(dirpath
,"/");
531 strcat(dirpath
,start
);
533 /* restore the / that we wiped out earlier */
537 /* the name has been resolved */
538 DEBUG(5,("conversion finished %s\n",name
));
543 /****************************************************************************
544 normalise for DOS usage
545 ****************************************************************************/
546 static void disk_norm(int *bsize
,int *dfree
,int *dsize
)
548 /* check if the disk is beyond the max disk size */
549 int maxdisksize
= lp_maxdisksize();
551 /* convert to blocks - and don't overflow */
552 maxdisksize
= ((maxdisksize
*1024)/(*bsize
))*1024;
553 if (*dsize
> maxdisksize
) *dsize
= maxdisksize
;
554 if (*dfree
> maxdisksize
) *dfree
= maxdisksize
-1; /* the -1 should stop
559 while (*dfree
> WORDMAX
|| *dsize
> WORDMAX
|| *bsize
< 512)
564 if (*bsize
> WORDMAX
)
567 if (*dsize
> WORDMAX
)
569 if (*dfree
> WORDMAX
)
576 /****************************************************************************
577 return number of 1K blocks available on a path and total number
578 ****************************************************************************/
579 int disk_free(char *path
,int *bsize
,int *dfree
,int *dsize
)
581 char *df_command
= lp_dfree_command();
595 if (disk_quotas(path
, bsize
, dfree
, dsize
))
597 disk_norm(bsize
,dfree
,dsize
);
598 return(((*bsize
)/1024)*(*dfree
));
603 /* possibly use system() to get the result */
604 if (df_command
&& *df_command
)
610 sprintf(outfile
,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
611 sprintf(syscmd
,"%s %s",df_command
,path
);
612 standard_sub_basic(syscmd
);
614 ret
= smbrun(syscmd
,outfile
,False
);
615 DEBUG(3,("Running the command `%s' gave %d\n",syscmd
,ret
));
618 FILE *f
= fopen(outfile
,"r");
624 fscanf(f
,"%d %d %d",dsize
,dfree
,bsize
);
628 DEBUG(0,("Can't open %s\n",outfile
));
632 disk_norm(bsize
,dfree
,dsize
);
633 return(((*bsize
)/1024)*(*dfree
));
637 DEBUG(1,("Warning - no statfs function\n"));
641 if (statfs(path
,&fs
,sizeof(fs
),0) != 0)
644 if (statvfs(path
, &fs
))
647 if (statfs(path
,&fs
,sizeof(fs
)) == -1)
649 if (statfs(path
,&fs
) == -1)
651 #endif /* USE_STATVFS */
654 DEBUG(3,("dfree call failed code errno=%d\n",errno
));
658 return(((*bsize
)/1024)*(*dfree
));
663 *dfree
= fs
.fd_req
.bfree
;
664 *dsize
= fs
.fd_req
.btot
;
667 *bsize
= fs
.f_frsize
;
670 /* eg: osf1 has f_fsize = fundamental filesystem block size,
671 f_bsize = optimal transfer block size (MX: 94-04-19) */
676 #endif /* USE_STATVFS */
681 *dfree
= fs
.f_bavail
;
683 *dsize
= fs
.f_blocks
;
686 #if defined(SCO) || defined(ISC) || defined(MIPS)
690 /* handle rediculous bsize values - some OSes are broken */
691 if ((*bsize
) < 512 || (*bsize
)>0xFFFF) *bsize
= 1024;
693 disk_norm(bsize
,dfree
,dsize
);
699 DEBUG(0,("dfree seems to be broken on your system\n"));
700 *dsize
= 20*1024*1024/(*bsize
);
701 *dfree
= MAX(1,*dfree
);
703 return(((*bsize
)/1024)*(*dfree
));
708 /****************************************************************************
709 wrap it to get filenames right
710 ****************************************************************************/
711 int sys_disk_free(char *path
,int *bsize
,int *dfree
,int *dsize
)
713 return(disk_free(dos_to_unix(path
,False
),bsize
,dfree
,dsize
));
718 /****************************************************************************
719 check a filename - possibly caling reducename
721 This is called by every routine before it allows an operation on a filename.
722 It does any final confirmation necessary to ensure that the filename is
723 a valid one for the user to access.
724 ****************************************************************************/
725 BOOL
check_name(char *name
,int cnum
)
731 if( is_vetoed_path(name
))
733 DEBUG(5,("file path name %s vetoed\n",name
));
737 ret
= reduce_name(name
,Connections
[cnum
].connectpath
,lp_widelinks(SNUM(cnum
)));
739 DEBUG(5,("check_name on %s failed\n",name
));
744 /****************************************************************************
745 check a filename - possibly caling reducename
746 ****************************************************************************/
747 static void check_for_pipe(char *fname
)
749 /* special case of pipe opens */
753 if (strstr(s
,"pipe/"))
755 DEBUG(3,("Rejecting named pipe open for %s\n",fname
));
756 unix_ERR_class
= ERRSRV
;
757 unix_ERR_code
= ERRaccess
;
761 /****************************************************************************
762 fd support routines - attempt to do a sys_open
763 ****************************************************************************/
765 int fd_attempt_open(char *fname
, int flags
, int mode
)
767 int fd
= sys_open(fname
,flags
,mode
);
769 /* Fix for files ending in '.' */
770 if((fd
== -1) && (errno
== ENOENT
) &&
771 (strchr(fname
,'.')==NULL
))
774 fd
= sys_open(fname
,flags
,mode
);
777 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
778 if ((fd
== -1) && (errno
== ENAMETOOLONG
))
781 char *p
= strrchr(fname
, '/');
783 if (p
== fname
) /* name is "/xxx" */
785 max_len
= pathconf("/", _PC_NAME_MAX
);
788 else if ((p
== NULL
) || (p
== fname
))
791 max_len
= pathconf(".", _PC_NAME_MAX
);
796 max_len
= pathconf(fname
, _PC_NAME_MAX
);
800 if (strlen(p
) > max_len
)
802 char tmp
= p
[max_len
];
805 if ((fd
= sys_open(fname
,flags
,mode
)) == -1)
813 /****************************************************************************
814 fd support routines - attempt to find an already open file by dev
815 and inode - increments the ref_count of the returned file_fd_struct *.
816 ****************************************************************************/
817 file_fd_struct
*fd_get_already_open(struct stat
*sbuf
)
820 file_fd_struct
*fd_ptr
;
825 for(i
= 0; i
<= max_file_fd_used
; i
++) {
827 if((fd_ptr
->ref_count
> 0) &&
828 (((int32
)sbuf
->st_dev
) == fd_ptr
->dev
) &&
829 (((int32
)sbuf
->st_ino
) == fd_ptr
->inode
)) {
832 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
833 i
, fd_ptr
->dev
, fd_ptr
->inode
, fd_ptr
->ref_count
));
840 /****************************************************************************
841 fd support routines - attempt to find a empty slot in the FileFd array.
842 Increments the ref_count of the returned entry.
843 ****************************************************************************/
844 file_fd_struct
*fd_get_new()
847 file_fd_struct
*fd_ptr
;
849 for(i
= 0; i
< MAX_OPEN_FILES
; i
++) {
851 if(fd_ptr
->ref_count
== 0) {
852 fd_ptr
->dev
= (int32
)-1;
853 fd_ptr
->inode
= (int32
)-1;
855 fd_ptr
->fd_readonly
= -1;
856 fd_ptr
->fd_writeonly
= -1;
857 fd_ptr
->real_open_flags
= -1;
859 /* Increment max used counter if neccessary, cuts down
860 on search time when re-using */
861 if(i
> max_file_fd_used
)
862 max_file_fd_used
= i
;
863 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
864 i
, fd_ptr
->dev
, fd_ptr
->inode
));
868 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
873 /****************************************************************************
874 fd support routines - attempt to re-open an already open fd as O_RDWR.
875 Save the already open fd (we cannot close due to POSIX file locking braindamage.
876 ****************************************************************************/
878 void fd_attempt_reopen(char *fname
, int mode
, file_fd_struct
*fd_ptr
)
880 int fd
= sys_open( fname
, O_RDWR
, mode
);
885 if(fd_ptr
->real_open_flags
== O_RDONLY
)
886 fd_ptr
->fd_readonly
= fd_ptr
->fd
;
887 if(fd_ptr
->real_open_flags
== O_WRONLY
)
888 fd_ptr
->fd_writeonly
= fd_ptr
->fd
;
891 fd_ptr
->real_open_flags
= O_RDWR
;
894 /****************************************************************************
895 fd support routines - attempt to close the file referenced by this fd.
896 Decrements the ref_count and returns it.
897 ****************************************************************************/
898 int fd_attempt_close(file_fd_struct
*fd_ptr
)
900 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
902 fd_ptr
->fd
, fd_ptr
->dev
, fd_ptr
->inode
,
903 fd_ptr
->real_open_flags
,
905 if(fd_ptr
->ref_count
> 0) {
907 if(fd_ptr
->ref_count
== 0) {
910 if(fd_ptr
->fd_readonly
!= -1)
911 close(fd_ptr
->fd_readonly
);
912 if(fd_ptr
->fd_writeonly
!= -1)
913 close(fd_ptr
->fd_writeonly
);
915 fd_ptr
->fd_readonly
= -1;
916 fd_ptr
->fd_writeonly
= -1;
917 fd_ptr
->real_open_flags
= -1;
922 return fd_ptr
->ref_count
;
925 /****************************************************************************
927 ****************************************************************************/
928 void open_file(int fnum
,int cnum
,char *fname1
,int flags
,int mode
, struct stat
*sbuf
)
930 extern struct current_user current_user
;
933 file_fd_struct
*fd_ptr
;
935 Files
[fnum
].open
= False
;
936 Files
[fnum
].fd_ptr
= 0;
939 strcpy(fname
,fname1
);
941 /* check permissions */
942 if ((flags
!= O_RDONLY
) && !CAN_WRITE(cnum
) && !Connections
[cnum
].printer
)
944 DEBUG(3,("Permission denied opening %s\n",fname
));
945 check_for_pipe(fname
);
949 /* this handles a bug in Win95 - it doesn't say to create the file when it
951 if (Connections
[cnum
].printer
)
955 if (flags == O_WRONLY)
956 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
960 /* XXXX - is this OK?? */
961 /* this works around a utime bug but can cause other problems */
962 if ((flags
& (O_WRONLY
|O_RDWR
)) && (flags
& O_CREAT
) && !(flags
& O_APPEND
))
967 * Ensure we have a valid struct stat so we can search the
971 if(stat(fname
, &statbuf
) < 0) {
972 if(errno
!= ENOENT
) {
973 DEBUG(3,("Error doing stat on file %s (%s)\n",
974 fname
,strerror(errno
)));
976 check_for_pipe(fname
);
986 * Check to see if we have this file already
987 * open. If we do, just use the already open fd and increment the
988 * reference count (fd_get_already_open increments the ref_count).
990 if((fd_ptr
= fd_get_already_open(sbuf
))!= 0) {
992 int accmode
= (flags
& (O_RDONLY
| O_WRONLY
| O_RDWR
));
994 /* File was already open. */
995 if((flags
& O_CREAT
) && (flags
& O_EXCL
)) {
1002 * If not opened O_RDWR try
1003 * and do that here - a chmod may have been done
1004 * between the last open and now.
1006 if(fd_ptr
->real_open_flags
!= O_RDWR
)
1007 fd_attempt_reopen(fname
, mode
, fd_ptr
);
1010 * Ensure that if we wanted write access
1011 * it has been opened for write, and if we wanted read it
1012 * was open for read.
1014 if(((accmode
== O_WRONLY
) && (fd_ptr
->real_open_flags
== O_RDONLY
)) ||
1015 ((accmode
== O_RDONLY
) && (fd_ptr
->real_open_flags
== O_WRONLY
)) ||
1016 ((accmode
== O_RDWR
) && (fd_ptr
->real_open_flags
!= O_RDWR
))) {
1017 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1018 fd_ptr
->real_open_flags
, fname
,strerror(EACCES
),flags
));
1019 check_for_pipe(fname
);
1020 fd_ptr
->ref_count
--;
1025 * If O_TRUNC was set, ensure we truncate the file.
1026 * open_file_shared explicitly clears this flag before
1027 * calling open_file, so we can safely do this here.
1030 ftruncate(fd_ptr
->fd
, 0);
1034 /* We need to allocate a new file_fd_struct (this increments the
1036 if((fd_ptr
= fd_get_new()) == 0)
1039 * Whatever the requested flags, attempt read/write access,
1040 * as we don't know what flags future file opens may require.
1041 * If this fails, try again with the required flags.
1042 * Even if we open read/write when only read access was
1043 * requested the setting of the can_write flag in
1044 * the file_struct will protect us from errant
1045 * write requests. We never need to worry about O_APPEND
1046 * as this is not set anywhere in Samba.
1048 fd_ptr
->real_open_flags
= O_RDWR
;
1049 /* Set the flags as needed without the read/write modes. */
1050 open_flags
= flags
& ~(O_RDWR
|O_WRONLY
|O_RDONLY
);
1051 fd_ptr
->fd
= fd_attempt_open(fname
, open_flags
|O_RDWR
, mode
);
1052 if((fd_ptr
->fd
== -1) && (errno
== EACCES
)) {
1053 if(flags
& O_WRONLY
) {
1054 fd_ptr
->fd
= fd_attempt_open(fname
, open_flags
|O_WRONLY
, mode
);
1055 fd_ptr
->real_open_flags
= O_WRONLY
;
1057 fd_ptr
->fd
= fd_attempt_open(fname
, open_flags
|O_RDONLY
, mode
);
1058 fd_ptr
->real_open_flags
= O_RDONLY
;
1063 if ((fd_ptr
->fd
>=0) &&
1064 Connections
[cnum
].printer
&& lp_minprintspace(SNUM(cnum
))) {
1068 strcpy(dname
,fname
);
1069 p
= strrchr(dname
,'/');
1071 if (sys_disk_free(dname
,&dum1
,&dum2
,&dum3
) <
1072 lp_minprintspace(SNUM(cnum
))) {
1073 fd_attempt_close(fd_ptr
);
1074 Files
[fnum
].fd_ptr
= 0;
1075 if(fd_ptr
->ref_count
== 0)
1084 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1085 fname
,strerror(errno
),flags
));
1086 /* Ensure the ref_count is decremented. */
1087 fd_attempt_close(fd_ptr
);
1088 check_for_pipe(fname
);
1092 if (fd_ptr
->fd
>= 0)
1096 if(fstat(fd_ptr
->fd
, &statbuf
) == -1) {
1097 /* Error - backout !! */
1098 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1099 fd_ptr
->fd
, fname
,strerror(errno
)));
1100 /* Ensure the ref_count is decremented. */
1101 fd_attempt_close(fd_ptr
);
1106 /* Set the correct entries in fd_ptr. */
1107 fd_ptr
->dev
= (int32
)sbuf
->st_dev
;
1108 fd_ptr
->inode
= (int32
)sbuf
->st_ino
;
1110 Files
[fnum
].fd_ptr
= fd_ptr
;
1111 Connections
[cnum
].num_files_open
++;
1112 Files
[fnum
].mode
= sbuf
->st_mode
;
1113 GetTimeOfDay(&Files
[fnum
].open_time
);
1114 Files
[fnum
].uid
= current_user
.id
;
1115 Files
[fnum
].size
= 0;
1116 Files
[fnum
].pos
= -1;
1117 Files
[fnum
].open
= True
;
1118 Files
[fnum
].mmap_ptr
= NULL
;
1119 Files
[fnum
].mmap_size
= 0;
1120 Files
[fnum
].can_lock
= True
;
1121 Files
[fnum
].can_read
= ((flags
& O_WRONLY
)==0);
1122 Files
[fnum
].can_write
= ((flags
& (O_WRONLY
|O_RDWR
))!=0);
1123 Files
[fnum
].share_mode
= 0;
1124 Files
[fnum
].share_pending
= False
;
1125 Files
[fnum
].print_file
= Connections
[cnum
].printer
;
1126 Files
[fnum
].modified
= False
;
1127 Files
[fnum
].cnum
= cnum
;
1128 string_set(&Files
[fnum
].name
,dos_to_unix(fname
,False
));
1129 Files
[fnum
].wbmpx_ptr
= NULL
;
1132 * If the printer is marked as postscript output a leading
1133 * file identifier to ensure the file is treated as a raw
1135 * This has a similar effect as CtrlD=0 in WIN.INI file.
1136 * tim@fsg.com 09/06/94
1138 if (Files
[fnum
].print_file
&& POSTSCRIPT(cnum
) &&
1139 Files
[fnum
].can_write
)
1141 DEBUG(3,("Writing postscript line\n"));
1142 write_file(fnum
,"%!\n",3);
1145 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1146 timestring(),Connections
[cnum
].user
,fname
,
1147 BOOLSTR(Files
[fnum
].can_read
),BOOLSTR(Files
[fnum
].can_write
),
1148 Connections
[cnum
].num_files_open
,fnum
));
1153 /* mmap it if read-only */
1154 if (!Files
[fnum
].can_write
)
1156 Files
[fnum
].mmap_size
= file_size(fname
);
1157 Files
[fnum
].mmap_ptr
= (char *)mmap(NULL
,Files
[fnum
].mmap_size
,
1158 PROT_READ
,MAP_SHARED
,Files
[fnum
].fd
,0);
1160 if (Files
[fnum
].mmap_ptr
== (char *)-1 || !Files
[fnum
].mmap_ptr
)
1162 DEBUG(3,("Failed to mmap() %s - %s\n",fname
,strerror(errno
)));
1163 Files
[fnum
].mmap_ptr
= NULL
;
1169 /*******************************************************************
1171 ********************************************************************/
1172 void sync_file(int fnum
)
1175 fsync(Files
[fnum
].fd_ptr
->fd
);
1179 /****************************************************************************
1180 run a file if it is a magic script
1181 ****************************************************************************/
1182 static void check_magic(int fnum
,int cnum
)
1184 if (!*lp_magicscript(SNUM(cnum
)))
1187 DEBUG(5,("checking magic for %s\n",Files
[fnum
].name
));
1191 if (!(p
= strrchr(Files
[fnum
].name
,'/')))
1192 p
= Files
[fnum
].name
;
1196 if (!strequal(lp_magicscript(SNUM(cnum
)),p
))
1202 pstring magic_output
;
1204 strcpy(fname
,Files
[fnum
].name
);
1206 if (*lp_magicoutput(SNUM(cnum
)))
1207 strcpy(magic_output
,lp_magicoutput(SNUM(cnum
)));
1209 sprintf(magic_output
,"%s.out",fname
);
1212 ret
= smbrun(fname
,magic_output
,False
);
1213 DEBUG(3,("Invoking magic command %s gave %d\n",fname
,ret
));
1219 /****************************************************************************
1220 close a file - possibly invalidating the read prediction
1221 ****************************************************************************/
1222 void close_file(int fnum
)
1224 int cnum
= Files
[fnum
].cnum
;
1225 invalidate_read_prediction(Files
[fnum
].fd_ptr
->fd
);
1226 Files
[fnum
].open
= False
;
1227 Connections
[cnum
].num_files_open
--;
1228 if(Files
[fnum
].wbmpx_ptr
)
1230 free((char *)Files
[fnum
].wbmpx_ptr
);
1231 Files
[fnum
].wbmpx_ptr
= NULL
;
1235 if(Files
[fnum
].mmap_ptr
)
1237 munmap(Files
[fnum
].mmap_ptr
,Files
[fnum
].mmap_size
);
1238 Files
[fnum
].mmap_ptr
= NULL
;
1242 if (lp_share_modes(SNUM(cnum
)))
1243 del_share_mode(fnum
);
1245 fd_attempt_close(Files
[fnum
].fd_ptr
);
1247 /* NT uses smbclose to start a print - weird */
1248 if (Files
[fnum
].print_file
)
1251 /* check for magic scripts */
1252 check_magic(fnum
,cnum
);
1254 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1255 timestring(),Connections
[cnum
].user
,Files
[fnum
].name
,
1256 Connections
[cnum
].num_files_open
));
1259 enum {AFAIL
,AREAD
,AWRITE
,AALL
};
1261 /*******************************************************************
1262 reproduce the share mode access table
1263 ********************************************************************/
1264 static int access_table(int new_deny
,int old_deny
,int old_mode
,
1265 int share_pid
,char *fname
)
1267 if (new_deny
== DENY_ALL
|| old_deny
== DENY_ALL
) return(AFAIL
);
1269 if (new_deny
== DENY_DOS
|| old_deny
== DENY_DOS
) {
1270 if (old_deny
== new_deny
&& share_pid
== getpid())
1273 if (old_mode
== 0) return(AREAD
);
1275 /* the new smbpub.zip spec says that if the file extension is
1276 .com, .dll, .exe or .sym then allow the open. I will force
1277 it to read-only as this seems sensible although the spec is
1278 a little unclear on this. */
1279 if ((fname
= strrchr(fname
,'.'))) {
1280 if (strequal(fname
,".com") ||
1281 strequal(fname
,".dll") ||
1282 strequal(fname
,".exe") ||
1283 strequal(fname
,".sym"))
1293 if (old_deny
==DENY_WRITE
&& old_mode
==0) return(AREAD
);
1294 if (old_deny
==DENY_READ
&& old_mode
==0) return(AWRITE
);
1295 if (old_deny
==DENY_NONE
&& old_mode
==0) return(AALL
);
1298 if (old_deny
==DENY_WRITE
&& old_mode
==1) return(AREAD
);
1299 if (old_deny
==DENY_READ
&& old_mode
==1) return(AWRITE
);
1300 if (old_deny
==DENY_NONE
&& old_mode
==1) return(AALL
);
1303 if (old_deny
==DENY_WRITE
) return(AREAD
);
1304 if (old_deny
==DENY_READ
) return(AWRITE
);
1305 if (old_deny
==DENY_NONE
) return(AALL
);
1311 /*******************************************************************
1312 check if the share mode on a file allows it to be deleted or unlinked
1313 return True if sharing doesn't prevent the operation
1314 ********************************************************************/
1315 BOOL
check_file_sharing(int cnum
,char *fname
)
1318 int share_mode
= get_share_mode_byname(cnum
,fname
,&pid
);
1320 if (!pid
|| !share_mode
) return(True
);
1322 if (share_mode
== DENY_DOS
)
1323 return(pid
== getpid());
1325 /* XXXX exactly what share mode combinations should be allowed for
1326 deleting/renaming? */
1330 /****************************************************************************
1332 Helper for open_file_shared.
1333 Truncate a file after checking locking; close file if locked.
1334 **************************************************************************/
1335 static void truncate_unless_locked(int fnum
, int cnum
)
1337 if (Files
[fnum
].can_write
){
1338 if (is_locked(fnum
,cnum
,0x3FFFFFFF,0)){
1341 unix_ERR_class
= ERRDOS
;
1342 unix_ERR_code
= ERRlock
;
1345 ftruncate(Files
[fnum
].fd_ptr
->fd
,0);
1350 /****************************************************************************
1351 open a file with a share mode
1352 ****************************************************************************/
1353 void open_file_shared(int fnum
,int cnum
,char *fname
,int share_mode
,int ofun
,
1354 int mode
,int *Access
,int *action
)
1358 int deny_mode
= (share_mode
>>4)&7;
1360 BOOL file_existed
= file_exist(fname
,&sbuf
);
1361 BOOL fcbopen
= False
;
1364 Files
[fnum
].open
= False
;
1365 Files
[fnum
].fd_ptr
= 0;
1367 /* this is for OS/2 EAs - try and say we don't support them */
1368 if (strstr(fname
,".+,;=[].")) {
1369 unix_ERR_class
= ERRDOS
;
1370 unix_ERR_code
= ERROR_EAS_NOT_SUPPORTED
;
1374 if ((ofun
& 0x3) == 0 && file_existed
) {
1381 if ((ofun
& 0x3) == 2)
1384 /* note that we ignore the append flag as
1385 append does not mean the same thing under dos and unix */
1387 switch (share_mode
&0xF)
1404 if (flags
!= O_RDONLY
&& file_existed
&&
1405 (!CAN_WRITE(cnum
) || IS_DOS_READONLY(dos_mode(cnum
,fname
,&sbuf
)))) {
1413 if (deny_mode
> DENY_NONE
&& deny_mode
!=DENY_FCB
) {
1414 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode
,fname
));
1419 if (deny_mode
== DENY_FCB
) deny_mode
= DENY_DOS
;
1421 if (lp_share_modes(SNUM(cnum
))) {
1425 old_share
= get_share_mode(cnum
,&sbuf
,&share_pid
);
1428 /* someone else has a share lock on it, check to see
1430 int old_open_mode
= old_share
&0xF;
1431 int old_deny_mode
= (old_share
>>4)&7;
1433 if (deny_mode
> 4 || old_deny_mode
> 4 || old_open_mode
> 2) {
1434 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1435 deny_mode
,old_deny_mode
,old_open_mode
,fname
));
1437 unix_ERR_class
= ERRDOS
;
1438 unix_ERR_code
= ERRbadshare
;
1443 int access_allowed
= access_table(deny_mode
,old_deny_mode
,old_open_mode
,
1446 if ((access_allowed
== AFAIL
) ||
1447 (!fcbopen
&& (access_allowed
== AREAD
&& flags
== O_RDWR
)) ||
1448 (access_allowed
== AREAD
&& flags
== O_WRONLY
) ||
1449 (access_allowed
== AWRITE
&& flags
== O_RDONLY
)) {
1450 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1451 deny_mode
,old_deny_mode
,old_open_mode
,
1455 unix_ERR_class
= ERRDOS
;
1456 unix_ERR_code
= ERRbadshare
;
1460 if (access_allowed
== AREAD
)
1463 if (access_allowed
== AWRITE
)
1469 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1470 flags
,flags2
,mode
));
1472 open_file(fnum
,cnum
,fname
,flags
|(flags2
&~(O_TRUNC
)),mode
,file_existed
? &sbuf
: 0);
1473 if (!Files
[fnum
].open
&& flags
==O_RDWR
&& errno
!=ENOENT
&& fcbopen
) {
1475 open_file(fnum
,cnum
,fname
,flags
,mode
,file_existed
? &sbuf
: 0 );
1478 if (Files
[fnum
].open
) {
1492 Files
[fnum
].share_mode
= (deny_mode
<<4) | open_mode
;
1493 Files
[fnum
].share_pending
= True
;
1496 (*Access
) = open_mode
;
1500 if (file_existed
&& !(flags2
& O_TRUNC
)) *action
= 1;
1501 if (!file_existed
) *action
= 2;
1502 if (file_existed
&& (flags2
& O_TRUNC
)) *action
= 3;
1506 share_mode_pending
= True
;
1508 if ((flags2
&O_TRUNC
) && file_existed
)
1509 truncate_unless_locked(fnum
,cnum
);
1515 /*******************************************************************
1516 check for files that we should now set our share modes on
1517 ********************************************************************/
1518 static void check_share_modes(void)
1521 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
1522 if(Files
[i
].open
&& Files
[i
].share_pending
) {
1523 if (lp_share_modes(SNUM(Files
[i
].cnum
))) {
1525 get_share_mode_by_fnum(Files
[i
].cnum
,i
,&pid
);
1527 set_share_mode(i
,Files
[i
].share_mode
);
1528 Files
[i
].share_pending
= False
;
1531 Files
[i
].share_pending
= False
;
1537 /****************************************************************************
1538 seek a file. Try to avoid the seek if possible
1539 ****************************************************************************/
1540 int seek_file(int fnum
,int pos
)
1543 if (Files
[fnum
].print_file
&& POSTSCRIPT(Files
[fnum
].cnum
))
1546 Files
[fnum
].pos
= lseek(Files
[fnum
].fd_ptr
->fd
,pos
+offset
,SEEK_SET
) - offset
;
1547 return(Files
[fnum
].pos
);
1550 /****************************************************************************
1552 ****************************************************************************/
1553 int read_file(int fnum
,char *data
,int pos
,int n
)
1557 if (!Files
[fnum
].can_write
)
1559 ret
= read_predict(Files
[fnum
].fd_ptr
->fd
,pos
,data
,NULL
,n
);
1567 if (Files
[fnum
].mmap_ptr
)
1569 int num
= MIN(n
,Files
[fnum
].mmap_size
-pos
);
1572 memcpy(data
,Files
[fnum
].mmap_ptr
+pos
,num
);
1584 if (seek_file(fnum
,pos
) != pos
)
1586 DEBUG(3,("Failed to seek to %d\n",pos
));
1591 readret
= read(Files
[fnum
].fd_ptr
->fd
,data
,n
);
1592 if (readret
> 0) ret
+= readret
;
1599 /****************************************************************************
1601 ****************************************************************************/
1602 int write_file(int fnum
,char *data
,int n
)
1604 if (!Files
[fnum
].can_write
) {
1609 if (!Files
[fnum
].modified
) {
1611 Files
[fnum
].modified
= True
;
1612 if (fstat(Files
[fnum
].fd_ptr
->fd
,&st
) == 0) {
1613 int dosmode
= dos_mode(Files
[fnum
].cnum
,Files
[fnum
].name
,&st
);
1614 if (MAP_ARCHIVE(Files
[fnum
].cnum
) && !IS_DOS_ARCHIVE(dosmode
)) {
1615 dos_chmod(Files
[fnum
].cnum
,Files
[fnum
].name
,dosmode
| aARCH
,&st
);
1620 return(write_data(Files
[fnum
].fd_ptr
->fd
,data
,n
));
1624 /****************************************************************************
1625 load parameters specific to a connection/service
1626 ****************************************************************************/
1627 BOOL
become_service(int cnum
,BOOL do_chdir
)
1629 extern char magic_char
;
1630 static int last_cnum
= -1;
1633 if (!OPEN_CNUM(cnum
))
1639 Connections
[cnum
].lastused
= smb_last_time
;
1644 ChDir(Connections
[cnum
].connectpath
) != 0 &&
1645 ChDir(Connections
[cnum
].origpath
) != 0)
1647 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1648 Connections
[cnum
].connectpath
,cnum
));
1652 if (cnum
== last_cnum
)
1657 case_default
= lp_defaultcase(snum
);
1658 case_preserve
= lp_preservecase(snum
);
1659 short_case_preserve
= lp_shortpreservecase(snum
);
1660 case_mangle
= lp_casemangle(snum
);
1661 case_sensitive
= lp_casesensitive(snum
);
1662 magic_char
= lp_magicchar(snum
);
1663 use_mangled_map
= (*lp_mangled_map(snum
) ? True
:False
);
1668 /****************************************************************************
1669 find a service entry
1670 ****************************************************************************/
1671 int find_service(char *service
)
1675 string_sub(service
,"\\","/");
1677 iService
= lp_servicenumber(service
);
1679 /* now handle the special case of a home directory */
1682 char *phome_dir
= get_home_dir(service
);
1683 DEBUG(3,("checking for home directory %s gave %s\n",service
,
1684 phome_dir
?phome_dir
:"(NULL)"));
1688 if ((iHomeService
= lp_servicenumber(HOMES_NAME
)) >= 0)
1690 lp_add_home(service
,iHomeService
,phome_dir
);
1691 iService
= lp_servicenumber(service
);
1696 /* If we still don't have a service, attempt to add it as a printer. */
1699 int iPrinterService
;
1701 if ((iPrinterService
= lp_servicenumber(PRINTERS_NAME
)) >= 0)
1705 DEBUG(3,("checking whether %s is a valid printer name...\n", service
));
1707 if ((pszTemp
!= NULL
) && pcap_printername_ok(service
, pszTemp
))
1709 DEBUG(3,("%s is a valid printer name\n", service
));
1710 DEBUG(3,("adding %s as a printer service\n", service
));
1711 lp_add_printer(service
,iPrinterService
);
1712 iService
= lp_servicenumber(service
);
1714 DEBUG(0,("failed to add %s as a printer service!\n", service
));
1717 DEBUG(3,("%s is not a valid printer name\n", service
));
1721 /* just possibly it's a default service? */
1724 char *defservice
= lp_defaultservice();
1725 if (defservice
&& *defservice
&& !strequal(defservice
,service
)) {
1726 iService
= find_service(defservice
);
1727 if (iService
>= 0) {
1728 string_sub(service
,"_","/");
1729 iService
= lp_add_service(service
,iService
);
1735 if (!VALID_SNUM(iService
))
1737 DEBUG(0,("Invalid snum %d for %s\n",iService
,service
));
1742 DEBUG(3,("find_service() failed to find service %s\n", service
));
1748 /****************************************************************************
1749 create an error packet from a cached error.
1750 ****************************************************************************/
1751 int cached_error_packet(char *inbuf
,char *outbuf
,int fnum
,int line
)
1753 write_bmpx_struct
*wbmpx
= Files
[fnum
].wbmpx_ptr
;
1755 int32 eclass
= wbmpx
->wr_errclass
;
1756 int32 err
= wbmpx
->wr_error
;
1758 /* We can now delete the auxiliary struct */
1759 free((char *)wbmpx
);
1760 Files
[fnum
].wbmpx_ptr
= NULL
;
1761 return error_packet(inbuf
,outbuf
,eclass
,err
,line
);
1770 } unix_smb_errmap
[] =
1772 {EPERM
,ERRDOS
,ERRnoaccess
},
1773 {EACCES
,ERRDOS
,ERRnoaccess
},
1774 {ENOENT
,ERRDOS
,ERRbadfile
},
1775 {EIO
,ERRHRD
,ERRgeneral
},
1776 {EBADF
,ERRSRV
,ERRsrverror
},
1777 {EINVAL
,ERRSRV
,ERRsrverror
},
1778 {EEXIST
,ERRDOS
,ERRfilexists
},
1779 {ENFILE
,ERRDOS
,ERRnofids
},
1780 {EMFILE
,ERRDOS
,ERRnofids
},
1781 {ENOSPC
,ERRHRD
,ERRdiskfull
},
1783 {EDQUOT
,ERRHRD
,ERRdiskfull
},
1786 {ENOTEMPTY
,ERRDOS
,ERRnoaccess
},
1789 {EXDEV
,ERRDOS
,ERRdiffdevice
},
1791 {EROFS
,ERRHRD
,ERRnowrite
},
1796 /****************************************************************************
1797 create an error packet from errno
1798 ****************************************************************************/
1799 int unix_error_packet(char *inbuf
,char *outbuf
,int def_class
,uint32 def_code
,int line
)
1801 int eclass
=def_class
;
1805 if (unix_ERR_class
!= SUCCESS
)
1807 eclass
= unix_ERR_class
;
1808 ecode
= unix_ERR_code
;
1809 unix_ERR_class
= SUCCESS
;
1814 while (unix_smb_errmap
[i
].smbclass
!= 0)
1816 if (unix_smb_errmap
[i
].unixerror
== errno
)
1818 eclass
= unix_smb_errmap
[i
].smbclass
;
1819 ecode
= unix_smb_errmap
[i
].smbcode
;
1826 return(error_packet(inbuf
,outbuf
,eclass
,ecode
,line
));
1830 /****************************************************************************
1831 create an error packet. Normally called using the ERROR() macro
1832 ****************************************************************************/
1833 int error_packet(char *inbuf
,char *outbuf
,int error_class
,uint32 error_code
,int line
)
1835 int outsize
= set_message(outbuf
,0,0,True
);
1837 cmd
= CVAL(inbuf
,smb_com
);
1839 CVAL(outbuf
,smb_rcls
) = error_class
;
1840 SSVAL(outbuf
,smb_err
,error_code
);
1842 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1845 (int)CVAL(inbuf
,smb_com
),
1846 smb_fn_name(CVAL(inbuf
,smb_com
)),
1851 DEBUG(3,("error string = %s\n",strerror(errno
)));
1857 #ifndef SIGCLD_IGNORE
1858 /****************************************************************************
1859 this prevents zombie child processes
1860 ****************************************************************************/
1861 static int sig_cld()
1863 static int depth
= 0;
1866 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
1872 BlockSignals(True
,SIGCLD
);
1873 DEBUG(5,("got SIGCLD\n"));
1876 while (sys_waitpid((pid_t
)-1,(int *)NULL
, WNOHANG
) > 0);
1880 /* Stevens, Adv. Unix Prog. says that on system V you must call
1881 wait before reinstalling the signal handler, because the kernel
1882 calls the handler from within the signal-call when there is a
1883 child that has exited. This would lead to an infinite recursion
1884 if done vice versa. */
1886 #ifndef DONT_REINSTALL_SIG
1887 #ifdef SIGCLD_IGNORE
1888 signal(SIGCLD
, SIG_IGN
);
1890 signal(SIGCLD
, SIGNAL_CAST sig_cld
);
1895 while (wait3(WAIT3_CAST1 NULL
, WNOHANG
, WAIT3_CAST2 NULL
) > 0);
1898 BlockSignals(False
,SIGCLD
);
1903 /****************************************************************************
1904 this is called when the client exits abruptly
1905 **************************************************************************/
1906 static int sig_pipe()
1908 extern int password_client
;
1909 BlockSignals(True
,SIGPIPE
);
1911 if (password_client
!= -1) {
1912 DEBUG(3,("lost connection to password server\n"));
1913 close(password_client
);
1914 password_client
= -1;
1915 #ifndef DONT_REINSTALL_SIG
1916 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
1918 BlockSignals(False
,SIGPIPE
);
1922 exit_server("Got sigpipe\n");
1926 /****************************************************************************
1927 open the socket communication
1928 ****************************************************************************/
1929 static BOOL
open_sockets(BOOL is_daemon
,int port
)
1936 struct sockaddr addr
;
1937 int in_addrlen
= sizeof(addr
);
1940 #ifdef SIGCLD_IGNORE
1941 signal(SIGCLD
, SIG_IGN
);
1943 signal(SIGCLD
, SIGNAL_CAST sig_cld
);
1946 /* open an incoming socket */
1947 s
= open_socket_in(SOCK_STREAM
, port
, 0,interpret_addr(lp_socket_address()));
1951 /* ready to listen */
1952 if (listen(s
, 5) == -1)
1954 DEBUG(0,("listen: %s",strerror(errno
)));
1962 /* now accept incoming connections - forking a new process
1963 for each incoming connection */
1964 DEBUG(2,("waiting for a connection\n"));
1967 Client
= accept(s
,&addr
,&in_addrlen
);
1969 if (Client
== -1 && errno
== EINTR
)
1974 DEBUG(0,("accept: %s",strerror(errno
)));
1978 #ifdef NO_FORK_DEBUG
1979 #ifndef NO_SIGNAL_TEST
1980 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
1981 signal(SIGCLD
, SIGNAL_CAST SIG_DFL
);
1985 if (Client
!= -1 && fork()==0)
1987 #ifndef NO_SIGNAL_TEST
1988 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
1989 signal(SIGCLD
, SIGNAL_CAST SIG_DFL
);
1991 /* close the listening socket */
1994 /* close our standard file descriptors */
1998 set_socket_options(Client
,"SO_KEEPALIVE");
1999 set_socket_options(Client
,user_socket_options
);
2003 close(Client
); /* The parent doesn't need this socket */
2009 /* We will abort gracefully when the client or remote system
2011 #ifndef NO_SIGNAL_TEST
2012 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
2016 /* close our standard file descriptors */
2019 set_socket_options(Client
,"SO_KEEPALIVE");
2020 set_socket_options(Client
,user_socket_options
);
2027 /****************************************************************************
2028 check if a snum is in use
2029 ****************************************************************************/
2030 BOOL
snum_used(int snum
)
2033 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2034 if (OPEN_CNUM(i
) && (SNUM(i
) == snum
))
2039 /****************************************************************************
2040 reload the services file
2041 **************************************************************************/
2042 BOOL
reload_services(BOOL test
)
2049 strcpy(fname
,lp_configfile());
2050 if (file_exist(fname
,NULL
) && !strcsequal(fname
,servicesf
))
2052 strcpy(servicesf
,fname
);
2059 if (test
&& !lp_file_list_changed())
2062 lp_killunused(snum_used
);
2064 ret
= lp_load(servicesf
,False
);
2066 /* perhaps the config filename is now set */
2068 reload_services(True
);
2077 set_socket_options(Client
,"SO_KEEPALIVE");
2078 set_socket_options(Client
,user_socket_options
);
2082 create_mangled_stack(lp_mangledstack());
2084 /* this forces service parameters to be flushed */
2085 become_service(-1,True
);
2092 /****************************************************************************
2093 this prevents zombie child processes
2094 ****************************************************************************/
2095 static int sig_hup()
2097 BlockSignals(True
,SIGHUP
);
2098 DEBUG(0,("Got SIGHUP\n"));
2099 reload_services(False
);
2100 #ifndef DONT_REINSTALL_SIG
2101 signal(SIGHUP
,SIGNAL_CAST sig_hup
);
2103 BlockSignals(False
,SIGHUP
);
2107 /****************************************************************************
2108 Setup the groups a user belongs to.
2109 ****************************************************************************/
2110 int setup_groups(char *user
, int uid
, int gid
, int *p_ngroups
,
2111 int **p_igroups
, gid_t
**p_groups
)
2113 if (-1 == initgroups(user
,gid
))
2117 DEBUG(0,("Unable to initgroups!\n"));
2118 if (gid
< 0 || gid
> 16000 || uid
< 0 || uid
> 16000)
2119 DEBUG(0,("This is probably a problem with the account %s\n",user
));
2127 ngroups
= getgroups(0,&grp
);
2130 igroups
= (int *)malloc(sizeof(int)*ngroups
);
2131 for (i
=0;i
<ngroups
;i
++)
2132 igroups
[i
] = 0x42424242;
2133 ngroups
= getgroups(ngroups
,(gid_t
*)igroups
);
2135 if (igroups
[0] == 0x42424242)
2138 *p_ngroups
= ngroups
;
2140 /* The following bit of code is very strange. It is due to the
2141 fact that some OSes use int* and some use gid_t* for
2142 getgroups, and some (like SunOS) use both, one in prototypes,
2143 and one in man pages and the actual code. Thus we detect it
2144 dynamically using some very ugly code */
2147 /* does getgroups return ints or gid_t ?? */
2148 static BOOL groups_use_ints
= True
;
2150 if (groups_use_ints
&&
2152 SVAL(igroups
,2) == 0x4242)
2153 groups_use_ints
= False
;
2155 for (i
=0;groups_use_ints
&& i
<ngroups
;i
++)
2156 if (igroups
[i
] == 0x42424242)
2157 groups_use_ints
= False
;
2159 if (groups_use_ints
)
2161 *p_igroups
= igroups
;
2162 *p_groups
= (gid_t
*)igroups
;
2166 gid_t
*groups
= (gid_t
*)igroups
;
2167 igroups
= (int *)malloc(sizeof(int)*ngroups
);
2168 for (i
=0;i
<ngroups
;i
++)
2169 igroups
[i
] = groups
[i
];
2170 *p_igroups
= igroups
;
2171 *p_groups
= (gid_t
*)groups
;
2174 DEBUG(3,("%s is in %d groups\n",user
,ngroups
));
2175 for (i
=0;i
<ngroups
;i
++)
2176 DEBUG(3,("%d ",igroups
[i
]));
2182 /****************************************************************************
2183 make a connection to a service
2184 ****************************************************************************/
2185 int make_connection(char *service
,char *user
,char *password
, int pwlen
, char *dev
,uint16 vuid
)
2189 struct passwd
*pass
= NULL
;
2190 connection_struct
*pcon
;
2193 static BOOL first_connection
= True
;
2197 snum
= find_service(service
);
2200 if (strequal(service
,"IPC$"))
2202 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2206 DEBUG(0,("%s couldn't find service %s\n",timestring(),service
));
2210 if (strequal(service
,HOMES_NAME
))
2212 if (*user
&& Get_Pwnam(user
,True
))
2213 return(make_connection(user
,user
,password
,pwlen
,dev
,vuid
));
2215 if (validated_username(vuid
))
2217 strcpy(user
,validated_username(vuid
));
2218 return(make_connection(user
,user
,password
,pwlen
,dev
,vuid
));
2222 if (!lp_snum_ok(snum
) || !check_access(snum
)) {
2226 /* you can only connect to the IPC$ service as an ipc device */
2227 if (strequal(service
,"IPC$"))
2230 if (*dev
== '?' || !*dev
)
2232 if (lp_print_ok(snum
))
2233 strcpy(dev
,"LPT1:");
2238 /* if the request is as a printer and you can't print then refuse */
2240 if (!lp_print_ok(snum
) && (strncmp(dev
,"LPT",3) == 0)) {
2241 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2245 /* lowercase the user name */
2248 /* add it as a possible user name */
2249 add_session_user(service
);
2251 /* shall we let them in? */
2252 if (!authorise_login(snum
,user
,password
,pwlen
,&guest
,&force
,vuid
))
2254 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service
));
2258 cnum
= find_free_connection(str_checksum(service
) + str_checksum(user
));
2261 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2265 pcon
= &Connections
[cnum
];
2266 bzero((char *)pcon
,sizeof(*pcon
));
2268 /* find out some info about the user */
2269 pass
= Get_Pwnam(user
,True
);
2273 DEBUG(0,("%s couldn't find account %s\n",timestring(),user
));
2277 pcon
->read_only
= lp_readonly(snum
);
2281 StrnCpy(list
,lp_readlist(snum
),sizeof(pstring
)-1);
2282 string_sub(list
,"%S",service
);
2284 if (user_in_list(user
,list
))
2285 pcon
->read_only
= True
;
2287 StrnCpy(list
,lp_writelist(snum
),sizeof(pstring
)-1);
2288 string_sub(list
,"%S",service
);
2290 if (user_in_list(user
,list
))
2291 pcon
->read_only
= False
;
2294 /* admin user check */
2295 if (user_in_list(user
,lp_admin_users(snum
)) &&
2298 pcon
->admin_user
= True
;
2299 DEBUG(0,("%s logged in as admin user (root privileges)\n",user
));
2302 pcon
->admin_user
= False
;
2304 pcon
->force_user
= force
;
2306 pcon
->uid
= pass
->pw_uid
;
2307 pcon
->gid
= pass
->pw_gid
;
2308 pcon
->num_files_open
= 0;
2309 pcon
->lastused
= time(NULL
);
2310 pcon
->service
= snum
;
2312 pcon
->printer
= (strncmp(dev
,"LPT",3) == 0);
2313 pcon
->ipc
= (strncmp(dev
,"IPC",3) == 0);
2314 pcon
->dirptr
= NULL
;
2315 string_set(&pcon
->dirpath
,"");
2316 string_set(&pcon
->user
,user
);
2319 if (*lp_force_group(snum
))
2324 StrnCpy(gname
,lp_force_group(snum
),sizeof(pstring
)-1);
2325 /* default service may be a group name */
2326 string_sub(gname
,"%S",service
);
2327 gptr
= (struct group
*)getgrnam(gname
);
2331 pcon
->gid
= gptr
->gr_gid
;
2332 DEBUG(3,("Forced group %s\n",gname
));
2335 DEBUG(1,("Couldn't find group %s\n",gname
));
2339 if (*lp_force_user(snum
))
2341 struct passwd
*pass2
;
2343 strcpy(fuser
,lp_force_user(snum
));
2344 pass2
= (struct passwd
*)Get_Pwnam(fuser
,True
);
2347 pcon
->uid
= pass2
->pw_uid
;
2348 string_set(&pcon
->user
,fuser
);
2350 pcon
->force_user
= True
;
2351 DEBUG(3,("Forced user %s\n",fuser
));
2354 DEBUG(1,("Couldn't find user %s\n",fuser
));
2359 strcpy(s
,lp_pathname(snum
));
2360 standard_sub(cnum
,s
);
2361 string_set(&pcon
->connectpath
,s
);
2362 DEBUG(3,("Connect path is %s\n",s
));
2365 /* groups stuff added by ih */
2367 pcon
->groups
= NULL
;
2371 /* Find all the groups this uid is in and store them. Used by become_user() */
2372 setup_groups(pcon
->user
,pcon
->uid
,pcon
->gid
,&pcon
->ngroups
,&pcon
->igroups
,&pcon
->groups
);
2374 /* check number of connections */
2375 if (!claim_connection(cnum
,
2376 lp_servicename(SNUM(cnum
)),
2377 lp_max_connections(SNUM(cnum
)),False
))
2379 DEBUG(1,("too many connections - rejected\n"));
2383 if (lp_status(SNUM(cnum
)))
2384 claim_connection(cnum
,"STATUS.",MAXSTATUS
,first_connection
);
2386 first_connection
= False
;
2391 /* execute any "root preexec = " line */
2392 if (*lp_rootpreexec(SNUM(cnum
)))
2395 strcpy(cmd
,lp_rootpreexec(SNUM(cnum
)));
2396 standard_sub(cnum
,cmd
);
2397 DEBUG(5,("cmd=%s\n",cmd
));
2398 smbrun(cmd
,NULL
,False
);
2401 if (!become_user(cnum
,pcon
->vuid
))
2403 DEBUG(0,("Can't become connected user!\n"));
2405 if (!IS_IPC(cnum
)) {
2406 yield_connection(cnum
,
2407 lp_servicename(SNUM(cnum
)),
2408 lp_max_connections(SNUM(cnum
)));
2409 if (lp_status(SNUM(cnum
))) yield_connection(cnum
,"STATUS.",MAXSTATUS
);
2414 if (ChDir(pcon
->connectpath
) != 0)
2416 DEBUG(0,("Can't change directory to %s (%s)\n",
2417 pcon
->connectpath
,strerror(errno
)));
2420 if (!IS_IPC(cnum
)) {
2421 yield_connection(cnum
,
2422 lp_servicename(SNUM(cnum
)),
2423 lp_max_connections(SNUM(cnum
)));
2424 if (lp_status(SNUM(cnum
))) yield_connection(cnum
,"STATUS.",MAXSTATUS
);
2429 string_set(&pcon
->origpath
,pcon
->connectpath
);
2431 #if SOFTLINK_OPTIMISATION
2432 /* resolve any soft links early */
2435 strcpy(s
,pcon
->connectpath
);
2437 string_set(&pcon
->connectpath
,s
);
2438 ChDir(pcon
->connectpath
);
2442 num_connections_open
++;
2443 add_session_user(user
);
2445 /* execute any "preexec = " line */
2446 if (*lp_preexec(SNUM(cnum
)))
2449 strcpy(cmd
,lp_preexec(SNUM(cnum
)));
2450 standard_sub(cnum
,cmd
);
2451 smbrun(cmd
,NULL
,False
);
2454 /* we've finished with the sensitive stuff */
2458 DEBUG(IS_IPC(cnum
)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2462 lp_servicename(SNUM(cnum
)),user
,
2472 /****************************************************************************
2473 find first available file slot
2474 ****************************************************************************/
2475 int find_free_file(void )
2478 /* we start at 1 here for an obscure reason I can't now remember,
2479 but I think is important :-) */
2480 for (i
=1;i
<MAX_OPEN_FILES
;i
++)
2483 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2487 /****************************************************************************
2488 find first available connection slot, starting from a random position.
2489 The randomisation stops problems with the server dieing and clients
2490 thinking the server is still available.
2491 ****************************************************************************/
2492 static int find_free_connection(int hash
)
2496 hash
= (hash
% (MAX_CONNECTIONS
-2))+1;
2500 for (i
=hash
+1;i
!=hash
;)
2502 if (!Connections
[i
].open
&& Connections
[i
].used
== used
)
2504 DEBUG(3,("found free connection number %d\n",i
));
2508 if (i
== MAX_CONNECTIONS
)
2518 DEBUG(1,("ERROR! Out of connection structures\n"));
2523 /****************************************************************************
2524 reply for the core protocol
2525 ****************************************************************************/
2526 int reply_corep(char *outbuf
)
2528 int outsize
= set_message(outbuf
,1,0,True
);
2530 Protocol
= PROTOCOL_CORE
;
2536 /****************************************************************************
2537 reply for the coreplus protocol
2538 ****************************************************************************/
2539 int reply_coreplus(char *outbuf
)
2541 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2542 int outsize
= set_message(outbuf
,13,0,True
);
2543 SSVAL(outbuf
,smb_vwv5
,raw
); /* tell redirector we support
2544 readbraw and writebraw (possibly) */
2545 CVAL(outbuf
,smb_flg
) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2546 SSVAL(outbuf
,smb_vwv1
,0x1); /* user level security, don't encrypt */
2548 Protocol
= PROTOCOL_COREPLUS
;
2554 /****************************************************************************
2555 reply for the lanman 1.0 protocol
2556 ****************************************************************************/
2557 int reply_lanman1(char *outbuf
)
2559 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2561 BOOL doencrypt
= SMBENCRYPT();
2562 time_t t
= time(NULL
);
2564 if (lp_security()>=SEC_USER
) secword
|= 1;
2565 if (doencrypt
) secword
|= 2;
2567 set_message(outbuf
,13,doencrypt
?8:0,True
);
2568 SSVAL(outbuf
,smb_vwv1
,secword
);
2570 /* Create a token value and add it to the outgoing packet. */
2572 generate_next_challenge(smb_buf(outbuf
));
2575 Protocol
= PROTOCOL_LANMAN1
;
2577 if (lp_security() == SEC_SERVER
&& server_cryptkey(outbuf
)) {
2578 DEBUG(3,("using password server validation\n"));
2580 if (doencrypt
) set_challenge(smb_buf(outbuf
));
2584 CVAL(outbuf
,smb_flg
) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2585 SSVAL(outbuf
,smb_vwv2
,maxxmit
);
2586 SSVAL(outbuf
,smb_vwv3
,lp_maxmux()); /* maxmux */
2587 SSVAL(outbuf
,smb_vwv4
,1);
2588 SSVAL(outbuf
,smb_vwv5
,raw
); /* tell redirector we support
2589 readbraw writebraw (possibly) */
2590 SIVAL(outbuf
,smb_vwv6
,getpid());
2591 SSVAL(outbuf
,smb_vwv10
, TimeDiff(t
)/60);
2593 put_dos_date(outbuf
,smb_vwv8
,t
);
2595 return (smb_len(outbuf
)+4);
2599 /****************************************************************************
2600 reply for the lanman 2.0 protocol
2601 ****************************************************************************/
2602 int reply_lanman2(char *outbuf
)
2604 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2606 BOOL doencrypt
= SMBENCRYPT();
2607 time_t t
= time(NULL
);
2609 if (lp_security()>=SEC_USER
) secword
|= 1;
2610 if (doencrypt
) secword
|= 2;
2612 set_message(outbuf
,13,doencrypt
?8:0,True
);
2613 SSVAL(outbuf
,smb_vwv1
,secword
);
2615 /* Create a token value and add it to the outgoing packet. */
2617 generate_next_challenge(smb_buf(outbuf
));
2620 SIVAL(outbuf
,smb_vwv6
,getpid());
2622 Protocol
= PROTOCOL_LANMAN2
;
2624 if (lp_security() == SEC_SERVER
&& server_cryptkey(outbuf
)) {
2625 DEBUG(3,("using password server validation\n"));
2627 if (doencrypt
) set_challenge(smb_buf(outbuf
));
2631 CVAL(outbuf
,smb_flg
) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2632 SSVAL(outbuf
,smb_vwv2
,maxxmit
);
2633 SSVAL(outbuf
,smb_vwv3
,lp_maxmux());
2634 SSVAL(outbuf
,smb_vwv4
,1);
2635 SSVAL(outbuf
,smb_vwv5
,raw
); /* readbraw and/or writebraw */
2636 SSVAL(outbuf
,smb_vwv10
, TimeDiff(t
)/60);
2637 put_dos_date(outbuf
,smb_vwv8
,t
);
2639 return (smb_len(outbuf
)+4);
2642 /****************************************************************************
2643 reply for the nt protocol
2644 ****************************************************************************/
2645 int reply_nt1(char *outbuf
)
2647 int capabilities
=0x300; /* has dual names + lock_and_read */
2649 BOOL doencrypt
= SMBENCRYPT();
2650 time_t t
= time(NULL
);
2652 if (lp_security()>=SEC_USER
) secword
|= 1;
2653 if (doencrypt
) secword
|= 2;
2655 set_message(outbuf
,17,doencrypt
?8:0,True
);
2656 CVAL(outbuf
,smb_vwv1
) = secword
;
2658 /* Create a token value and add it to the outgoing packet. */
2660 generate_next_challenge(smb_buf(outbuf
));
2661 /* Tell the nt machine how long the challenge is. */
2662 SSVALS(outbuf
,smb_vwv16
+1,8);
2666 SIVAL(outbuf
,smb_vwv7
+1,getpid()); /* session key */
2668 Protocol
= PROTOCOL_NT1
;
2670 if (lp_security() == SEC_SERVER
&& server_cryptkey(outbuf
)) {
2671 DEBUG(3,("using password server validation\n"));
2673 if (doencrypt
) set_challenge(smb_buf(outbuf
));
2677 if (lp_readraw() && lp_writeraw())
2680 SSVAL(outbuf
,smb_vwv1
+1,lp_maxmux()); /* maxmpx */
2681 SSVAL(outbuf
,smb_vwv2
+1,1); /* num vcs */
2682 SIVAL(outbuf
,smb_vwv3
+1,0xFFFF); /* max buffer */
2683 SIVAL(outbuf
,smb_vwv5
+1,0xFFFF); /* raw size */
2684 SIVAL(outbuf
,smb_vwv9
+1,capabilities
); /* capabilities */
2685 put_long_date(outbuf
+smb_vwv11
+1,t
);
2686 SSVALS(outbuf
,smb_vwv15
+1,TimeDiff(t
)/60);
2688 return (smb_len(outbuf
)+4);
2692 /* these are the protocol lists used for auto architecture detection:
2695 protocol [PC NETWORK PROGRAM 1.0]
2696 protocol [XENIX CORE]
2697 protocol [MICROSOFT NETWORKS 1.03]
2698 protocol [LANMAN1.0]
2699 protocol [Windows for Workgroups 3.1a]
2700 protocol [LM1.2X002]
2701 protocol [LANMAN2.1]
2702 protocol [NT LM 0.12]
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 [LANMAN1.0]
2718 protocol [LM1.2X002]
2719 protocol [LANMAN2.1]
2723 * Modified to recognize the architecture of the remote machine better.
2725 * This appears to be the matrix of which protocol is used by which
2727 Protocol WfWg Win95 WinNT OS/2
2728 PC NETWORK PROGRAM 1.0 1 1 1 1
2730 MICROSOFT NETWORKS 3.0 2 2
2732 MICROSOFT NETWORKS 1.03 3
2735 Windows for Workgroups 3.1a 5 5 5
2740 * tim@fsg.com 09/29/95
2743 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2744 #define ARCH_WIN95 0x2
2745 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2746 #define ARCH_WINNT 0x8
2747 #define ARCH_SAMBA 0x10
2749 #define ARCH_ALL 0x1F
2751 /* List of supported protocols, most desired first */
2755 int (*proto_reply_fn
)(char *);
2757 } supported_protocols
[] = {
2758 {"NT LANMAN 1.0", "NT1", reply_nt1
, PROTOCOL_NT1
},
2759 {"NT LM 0.12", "NT1", reply_nt1
, PROTOCOL_NT1
},
2760 {"LM1.2X002", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
2761 {"Samba", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
2762 {"DOS LM1.2X002", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
2763 {"LANMAN1.0", "LANMAN1", reply_lanman1
, PROTOCOL_LANMAN1
},
2764 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1
, PROTOCOL_LANMAN1
},
2765 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus
, PROTOCOL_COREPLUS
},
2766 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep
, PROTOCOL_CORE
},
2771 /****************************************************************************
2773 ****************************************************************************/
2774 static int reply_negprot(char *inbuf
,char *outbuf
)
2776 extern fstring remote_arch
;
2777 int outsize
= set_message(outbuf
,1,0,True
);
2782 int bcc
= SVAL(smb_buf(inbuf
),-2);
2783 int arch
= ARCH_ALL
;
2785 p
= smb_buf(inbuf
)+1;
2786 while (p
< (smb_buf(inbuf
) + bcc
))
2789 DEBUG(3,("Requested protocol [%s]\n",p
));
2790 if (strcsequal(p
,"Windows for Workgroups 3.1a"))
2791 arch
&= ( ARCH_WFWG
| ARCH_WIN95
| ARCH_WINNT
);
2792 else if (strcsequal(p
,"DOS LM1.2X002"))
2793 arch
&= ( ARCH_WFWG
| ARCH_WIN95
);
2794 else if (strcsequal(p
,"DOS LANMAN2.1"))
2795 arch
&= ( ARCH_WFWG
| ARCH_WIN95
);
2796 else if (strcsequal(p
,"NT LM 0.12"))
2797 arch
&= ( ARCH_WIN95
| ARCH_WINNT
);
2798 else if (strcsequal(p
,"LANMAN2.1"))
2799 arch
&= ( ARCH_WINNT
| ARCH_OS2
);
2800 else if (strcsequal(p
,"LM1.2X002"))
2801 arch
&= ( ARCH_WINNT
| ARCH_OS2
);
2802 else if (strcsequal(p
,"MICROSOFT NETWORKS 1.03"))
2804 else if (strcsequal(p
,"XENIX CORE"))
2805 arch
&= ( ARCH_WINNT
| ARCH_OS2
);
2806 else if (strcsequal(p
,"Samba")) {
2816 strcpy(remote_arch
,"Samba");
2819 strcpy(remote_arch
,"WfWg");
2822 strcpy(remote_arch
,"Win95");
2825 strcpy(remote_arch
,"WinNT");
2828 strcpy(remote_arch
,"OS2");
2831 strcpy(remote_arch
,"UNKNOWN");
2835 /* possibly reload - change of architecture */
2836 reload_services(True
);
2838 /* a special case to stop password server loops */
2839 if (Index
== 1 && strequal(remote_machine
,myhostname
) &&
2840 lp_security()==SEC_SERVER
)
2841 exit_server("Password server loop!");
2843 /* Check for protocols, most desirable first */
2844 for (protocol
= 0; supported_protocols
[protocol
].proto_name
; protocol
++)
2846 p
= smb_buf(inbuf
)+1;
2848 if (lp_maxprotocol() >= supported_protocols
[protocol
].protocol_level
)
2849 while (p
< (smb_buf(inbuf
) + bcc
))
2851 if (strequal(p
,supported_protocols
[protocol
].proto_name
))
2860 SSVAL(outbuf
,smb_vwv0
,choice
);
2862 extern fstring remote_proto
;
2863 strcpy(remote_proto
,supported_protocols
[protocol
].short_name
);
2864 reload_services(True
);
2865 outsize
= supported_protocols
[protocol
].proto_reply_fn(outbuf
);
2866 DEBUG(3,("Selected protocol %s\n",supported_protocols
[protocol
].proto_name
));
2869 DEBUG(0,("No protocol supported !\n"));
2871 SSVAL(outbuf
,smb_vwv0
,choice
);
2873 DEBUG(5,("%s negprot index=%d\n",timestring(),choice
));
2879 /****************************************************************************
2880 close all open files for a connection
2881 ****************************************************************************/
2882 static void close_open_files(int cnum
)
2885 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
2886 if( Files
[i
].cnum
== cnum
&& Files
[i
].open
) {
2893 /****************************************************************************
2895 ****************************************************************************/
2896 void close_cnum(int cnum
, uint16 vuid
)
2898 DirCacheFlush(SNUM(cnum
));
2902 if (!OPEN_CNUM(cnum
))
2904 DEBUG(0,("Can't close cnum %d\n",cnum
));
2908 DEBUG(IS_IPC(cnum
)?3:1,("%s %s (%s) closed connection to service %s\n",
2910 remote_machine
,client_addr(),
2911 lp_servicename(SNUM(cnum
))));
2913 yield_connection(cnum
,
2914 lp_servicename(SNUM(cnum
)),
2915 lp_max_connections(SNUM(cnum
)));
2917 if (lp_status(SNUM(cnum
)))
2918 yield_connection(cnum
,"STATUS.",MAXSTATUS
);
2920 close_open_files(cnum
);
2921 dptr_closecnum(cnum
);
2923 /* execute any "postexec = " line */
2924 if (*lp_postexec(SNUM(cnum
)) && become_user(cnum
,vuid
))
2927 strcpy(cmd
,lp_postexec(SNUM(cnum
)));
2928 standard_sub(cnum
,cmd
);
2929 smbrun(cmd
,NULL
,False
);
2934 /* execute any "root postexec = " line */
2935 if (*lp_rootpostexec(SNUM(cnum
)))
2938 strcpy(cmd
,lp_rootpostexec(SNUM(cnum
)));
2939 standard_sub(cnum
,cmd
);
2940 smbrun(cmd
,NULL
,False
);
2943 Connections
[cnum
].open
= False
;
2944 num_connections_open
--;
2945 if (Connections
[cnum
].ngroups
&& Connections
[cnum
].groups
)
2947 if (Connections
[cnum
].igroups
!= (int *)Connections
[cnum
].groups
)
2948 free(Connections
[cnum
].groups
);
2949 free(Connections
[cnum
].igroups
);
2950 Connections
[cnum
].groups
= NULL
;
2951 Connections
[cnum
].igroups
= NULL
;
2952 Connections
[cnum
].ngroups
= 0;
2955 string_set(&Connections
[cnum
].user
,"");
2956 string_set(&Connections
[cnum
].dirpath
,"");
2957 string_set(&Connections
[cnum
].connectpath
,"");
2961 /****************************************************************************
2962 simple routines to do connection counting
2963 ****************************************************************************/
2964 BOOL
yield_connection(int cnum
,char *name
,int max_connections
)
2966 struct connect_record crec
;
2969 int mypid
= getpid();
2972 DEBUG(3,("Yielding connection to %d %s\n",cnum
,name
));
2974 if (max_connections
<= 0)
2977 bzero(&crec
,sizeof(crec
));
2979 strcpy(fname
,lp_lockdir());
2980 standard_sub(cnum
,fname
);
2981 trim_string(fname
,"","/");
2985 strcat(fname
,".LCK");
2987 f
= fopen(fname
,"r+");
2990 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname
,strerror(errno
)));
2994 fseek(f
,0,SEEK_SET
);
2996 /* find a free spot */
2997 for (i
=0;i
<max_connections
;i
++)
2999 if (fread(&crec
,sizeof(crec
),1,f
) != 1)
3001 DEBUG(2,("Entry not found in lock file %s\n",fname
));
3005 if (crec
.pid
== mypid
&& crec
.cnum
== cnum
)
3009 if (crec
.pid
!= mypid
|| crec
.cnum
!= cnum
)
3012 DEBUG(2,("Entry not found in lock file %s\n",fname
));
3016 bzero((void *)&crec
,sizeof(crec
));
3018 /* remove our mark */
3019 if (fseek(f
,i
*sizeof(crec
),SEEK_SET
) != 0 ||
3020 fwrite(&crec
,sizeof(crec
),1,f
) != 1)
3022 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname
,strerror(errno
)));
3027 DEBUG(3,("Yield successful\n"));
3034 /****************************************************************************
3035 simple routines to do connection counting
3036 ****************************************************************************/
3037 BOOL
claim_connection(int cnum
,char *name
,int max_connections
,BOOL Clear
)
3039 struct connect_record crec
;
3042 int snum
= SNUM(cnum
);
3046 if (max_connections
<= 0)
3049 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name
,max_connections
));
3051 strcpy(fname
,lp_lockdir());
3052 standard_sub(cnum
,fname
);
3053 trim_string(fname
,"","/");
3055 if (!directory_exist(fname
,NULL
))
3060 strcat(fname
,".LCK");
3062 if (!file_exist(fname
,NULL
))
3064 int oldmask
= umask(022);
3065 f
= fopen(fname
,"w");
3070 total_recs
= file_size(fname
) / sizeof(crec
);
3072 f
= fopen(fname
,"r+");
3076 DEBUG(1,("couldn't open lock file %s\n",fname
));
3080 /* find a free spot */
3081 for (i
=0;i
<max_connections
;i
++)
3084 if (i
>=total_recs
||
3085 fseek(f
,i
*sizeof(crec
),SEEK_SET
) != 0 ||
3086 fread(&crec
,sizeof(crec
),1,f
) != 1)
3088 if (foundi
< 0) foundi
= i
;
3092 if (Clear
&& crec
.pid
&& !process_exists(crec
.pid
))
3094 fseek(f
,i
*sizeof(crec
),SEEK_SET
);
3095 bzero((void *)&crec
,sizeof(crec
));
3096 fwrite(&crec
,sizeof(crec
),1,f
);
3097 if (foundi
< 0) foundi
= i
;
3100 if (foundi
< 0 && (!crec
.pid
|| !process_exists(crec
.pid
)))
3109 DEBUG(3,("no free locks in %s\n",fname
));
3114 /* fill in the crec */
3115 bzero((void *)&crec
,sizeof(crec
));
3116 crec
.magic
= 0x280267;
3117 crec
.pid
= getpid();
3119 crec
.uid
= Connections
[cnum
].uid
;
3120 crec
.gid
= Connections
[cnum
].gid
;
3121 StrnCpy(crec
.name
,lp_servicename(snum
),sizeof(crec
.name
)-1);
3122 crec
.start
= time(NULL
);
3124 StrnCpy(crec
.machine
,remote_machine
,sizeof(crec
.machine
)-1);
3125 StrnCpy(crec
.addr
,client_addr(),sizeof(crec
.addr
)-1);
3128 if (fseek(f
,foundi
*sizeof(crec
),SEEK_SET
) != 0 ||
3129 fwrite(&crec
,sizeof(crec
),1,f
) != 1)
3140 /*******************************************************************
3141 prepare to dump a core file - carefully!
3142 ********************************************************************/
3143 static BOOL
dump_core(void)
3147 strcpy(dname
,debugf
);
3148 if ((p
=strrchr(dname
,'/'))) *p
=0;
3149 strcat(dname
,"/corefiles");
3151 sys_chown(dname
,getuid(),getgid());
3153 if (chdir(dname
)) return(False
);
3156 #ifndef NO_GETRLIMIT
3160 getrlimit(RLIMIT_CORE
, &rlp
);
3161 rlp
.rlim_cur
= MAX(4*1024*1024,rlp
.rlim_cur
);
3162 setrlimit(RLIMIT_CORE
, &rlp
);
3163 getrlimit(RLIMIT_CORE
, &rlp
);
3164 DEBUG(3,("Core limits now %d %d\n",rlp
.rlim_cur
,rlp
.rlim_max
));
3170 DEBUG(0,("Dumping core in %s\n",dname
));
3175 /****************************************************************************
3177 ****************************************************************************/
3178 void exit_server(char *reason
)
3180 static int firsttime
=1;
3183 if (!firsttime
) exit(0);
3187 DEBUG(2,("Closing connections\n"));
3188 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
3189 if (Connections
[i
].open
)
3192 if (dcelogin_atmost_once
)
3196 int oldlevel
= DEBUGLEVEL
;
3198 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message
)));
3200 show_msg(last_inbuf
);
3201 DEBUGLEVEL
= oldlevel
;
3202 DEBUG(0,("===============================================================\n"));
3204 if (dump_core()) return;
3208 #if FAST_SHARE_MODES
3209 stop_share_mode_mgmt();
3212 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason
?reason
:""));
3216 /****************************************************************************
3217 do some standard substitutions in a string
3218 ****************************************************************************/
3219 void standard_sub(int cnum
,char *s
)
3221 if (!strchr(s
,'%')) return;
3223 if (VALID_CNUM(cnum
))
3225 string_sub(s
,"%S",lp_servicename(Connections
[cnum
].service
));
3226 string_sub(s
,"%P",Connections
[cnum
].connectpath
);
3227 string_sub(s
,"%u",Connections
[cnum
].user
);
3228 if (strstr(s
,"%H")) {
3229 char *home
= get_home_dir(Connections
[cnum
].user
);
3230 if (home
) string_sub(s
,"%H",home
);
3232 string_sub(s
,"%g",gidtoname(Connections
[cnum
].gid
));
3234 standard_sub_basic(s
);
3238 These flags determine some of the permissions required to do an operation
3240 Note that I don't set NEED_WRITE on some write operations because they
3241 are used by some brain-dead clients when printing, and I don't want to
3242 force write permissions on print services.
3244 #define AS_USER (1<<0)
3245 #define NEED_WRITE (1<<1)
3246 #define TIME_INIT (1<<2)
3247 #define CAN_IPC (1<<3)
3248 #define AS_GUEST (1<<5)
3252 define a list of possible SMB messages and their corresponding
3253 functions. Any message that has a NULL function is unimplemented -
3254 please feel free to contribute implementations!
3256 struct smb_message_struct
3270 {SMBnegprot
,"SMBnegprot",reply_negprot
,0},
3271 {SMBtcon
,"SMBtcon",reply_tcon
,0},
3272 {SMBtdis
,"SMBtdis",reply_tdis
,0},
3273 {SMBexit
,"SMBexit",reply_exit
,0},
3274 {SMBioctl
,"SMBioctl",reply_ioctl
,0},
3275 {SMBecho
,"SMBecho",reply_echo
,0},
3276 {SMBsesssetupX
,"SMBsesssetupX",reply_sesssetup_and_X
,0},
3277 {SMBtconX
,"SMBtconX",reply_tcon_and_X
,0},
3278 {SMBulogoffX
, "SMBulogoffX", reply_ulogoffX
, 0}, /* ulogoff doesn't give a valid TID */
3279 {SMBgetatr
,"SMBgetatr",reply_getatr
,AS_USER
},
3280 {SMBsetatr
,"SMBsetatr",reply_setatr
,AS_USER
| NEED_WRITE
},
3281 {SMBchkpth
,"SMBchkpth",reply_chkpth
,AS_USER
},
3282 {SMBsearch
,"SMBsearch",reply_search
,AS_USER
},
3283 {SMBopen
,"SMBopen",reply_open
,AS_USER
},
3285 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3286 {SMBcreate
,"SMBcreate",reply_mknew
,AS_USER
},
3287 {SMBmknew
,"SMBmknew",reply_mknew
,AS_USER
},
3289 {SMBunlink
,"SMBunlink",reply_unlink
,AS_USER
| NEED_WRITE
},
3290 {SMBread
,"SMBread",reply_read
,AS_USER
},
3291 {SMBwrite
,"SMBwrite",reply_write
,AS_USER
},
3292 {SMBclose
,"SMBclose",reply_close
,AS_USER
| CAN_IPC
},
3293 {SMBmkdir
,"SMBmkdir",reply_mkdir
,AS_USER
| NEED_WRITE
},
3294 {SMBrmdir
,"SMBrmdir",reply_rmdir
,AS_USER
| NEED_WRITE
},
3295 {SMBdskattr
,"SMBdskattr",reply_dskattr
,AS_USER
},
3296 {SMBmv
,"SMBmv",reply_mv
,AS_USER
| NEED_WRITE
},
3298 /* this is a Pathworks specific call, allowing the
3299 changing of the root path */
3300 {pSETDIR
,"pSETDIR",reply_setdir
,AS_USER
},
3302 {SMBlseek
,"SMBlseek",reply_lseek
,AS_USER
},
3303 {SMBflush
,"SMBflush",reply_flush
,AS_USER
},
3304 {SMBctemp
,"SMBctemp",reply_ctemp
,AS_USER
},
3305 {SMBsplopen
,"SMBsplopen",reply_printopen
,AS_USER
},
3306 {SMBsplclose
,"SMBsplclose",reply_printclose
,AS_USER
},
3307 {SMBsplretq
,"SMBsplretq",reply_printqueue
,AS_USER
|AS_GUEST
},
3308 {SMBsplwr
,"SMBsplwr",reply_printwrite
,AS_USER
},
3309 {SMBlock
,"SMBlock",reply_lock
,AS_USER
},
3310 {SMBunlock
,"SMBunlock",reply_unlock
,AS_USER
},
3312 /* CORE+ PROTOCOL FOLLOWS */
3314 {SMBreadbraw
,"SMBreadbraw",reply_readbraw
,AS_USER
},
3315 {SMBwritebraw
,"SMBwritebraw",reply_writebraw
,AS_USER
},
3316 {SMBwriteclose
,"SMBwriteclose",reply_writeclose
,AS_USER
},
3317 {SMBlockread
,"SMBlockread",reply_lockread
,AS_USER
},
3318 {SMBwriteunlock
,"SMBwriteunlock",reply_writeunlock
,AS_USER
},
3320 /* LANMAN1.0 PROTOCOL FOLLOWS */
3322 {SMBreadBmpx
,"SMBreadBmpx",reply_readbmpx
,AS_USER
},
3323 {SMBreadBs
,"SMBreadBs",NULL
,AS_USER
},
3324 {SMBwriteBmpx
,"SMBwriteBmpx",reply_writebmpx
,AS_USER
},
3325 {SMBwriteBs
,"SMBwriteBs",reply_writebs
,AS_USER
},
3326 {SMBwritec
,"SMBwritec",NULL
,AS_USER
},
3327 {SMBsetattrE
,"SMBsetattrE",reply_setattrE
,AS_USER
| NEED_WRITE
},
3328 {SMBgetattrE
,"SMBgetattrE",reply_getattrE
,AS_USER
},
3329 {SMBtrans
,"SMBtrans",reply_trans
,AS_USER
| CAN_IPC
},
3330 {SMBtranss
,"SMBtranss",NULL
,AS_USER
| CAN_IPC
},
3331 {SMBioctls
,"SMBioctls",NULL
,AS_USER
},
3332 {SMBcopy
,"SMBcopy",reply_copy
,AS_USER
| NEED_WRITE
},
3333 {SMBmove
,"SMBmove",NULL
,AS_USER
| NEED_WRITE
},
3335 {SMBopenX
,"SMBopenX",reply_open_and_X
,AS_USER
| CAN_IPC
},
3336 {SMBreadX
,"SMBreadX",reply_read_and_X
,AS_USER
},
3337 {SMBwriteX
,"SMBwriteX",reply_write_and_X
,AS_USER
},
3338 {SMBlockingX
,"SMBlockingX",reply_lockingX
,AS_USER
},
3340 {SMBffirst
,"SMBffirst",reply_search
,AS_USER
},
3341 {SMBfunique
,"SMBfunique",reply_search
,AS_USER
},
3342 {SMBfclose
,"SMBfclose",reply_fclose
,AS_USER
},
3344 /* LANMAN2.0 PROTOCOL FOLLOWS */
3345 {SMBfindnclose
, "SMBfindnclose", reply_findnclose
, AS_USER
},
3346 {SMBfindclose
, "SMBfindclose", reply_findclose
,AS_USER
},
3347 {SMBtrans2
, "SMBtrans2", reply_trans2
, AS_USER
},
3348 {SMBtranss2
, "SMBtranss2", reply_transs2
, AS_USER
},
3350 /* messaging routines */
3351 {SMBsends
,"SMBsends",reply_sends
,AS_GUEST
},
3352 {SMBsendstrt
,"SMBsendstrt",reply_sendstrt
,AS_GUEST
},
3353 {SMBsendend
,"SMBsendend",reply_sendend
,AS_GUEST
},
3354 {SMBsendtxt
,"SMBsendtxt",reply_sendtxt
,AS_GUEST
},
3356 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3358 {SMBsendb
,"SMBsendb",NULL
,AS_GUEST
},
3359 {SMBfwdname
,"SMBfwdname",NULL
,AS_GUEST
},
3360 {SMBcancelf
,"SMBcancelf",NULL
,AS_GUEST
},
3361 {SMBgetmac
,"SMBgetmac",NULL
,AS_GUEST
}
3364 /****************************************************************************
3365 return a string containing the function name of a SMB command
3366 ****************************************************************************/
3367 char *smb_fn_name(int type
)
3369 static char *unknown_name
= "SMBunknown";
3370 static int num_smb_messages
=
3371 sizeof(smb_messages
) / sizeof(struct smb_message_struct
);
3374 for (match
=0;match
<num_smb_messages
;match
++)
3375 if (smb_messages
[match
].code
== type
)
3378 if (match
== num_smb_messages
)
3379 return(unknown_name
);
3381 return(smb_messages
[match
].name
);
3385 /****************************************************************************
3386 do a switch on the message type, and return the response size
3387 ****************************************************************************/
3388 static int switch_message(int type
,char *inbuf
,char *outbuf
,int size
,int bufsize
)
3392 static int num_smb_messages
=
3393 sizeof(smb_messages
) / sizeof(struct smb_message_struct
);
3397 struct timeval msg_start_time
;
3398 struct timeval msg_end_time
;
3399 static unsigned long total_time
= 0;
3401 GetTimeOfDay(&msg_start_time
);
3408 last_message
= type
;
3410 /* make sure this is an SMB packet */
3411 if (strncmp(smb_base(inbuf
),"\377SMB",4) != 0)
3413 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf
)));
3417 for (match
=0;match
<num_smb_messages
;match
++)
3418 if (smb_messages
[match
].code
== type
)
3421 if (match
== num_smb_messages
)
3423 DEBUG(0,("Unknown message type %d!\n",type
));
3424 outsize
= reply_unknown(inbuf
,outbuf
);
3428 DEBUG(3,("switch message %s (pid %d)\n",smb_messages
[match
].name
,pid
));
3429 if (smb_messages
[match
].fn
)
3431 int cnum
= SVAL(inbuf
,smb_tid
);
3432 int flags
= smb_messages
[match
].flags
;
3433 uint16 session_tag
= SVAL(inbuf
,smb_uid
);
3435 /* does this protocol need to be run as root? */
3436 if (!(flags
& AS_USER
))
3439 /* does this protocol need to be run as the connected user? */
3440 if ((flags
& AS_USER
) && !become_user(cnum
,session_tag
)) {
3441 if (flags
& AS_GUEST
)
3444 return(ERROR(ERRSRV
,ERRinvnid
));
3446 /* this code is to work around a bug is MS client 3 without
3447 introducing a security hole - it needs to be able to do
3448 print queue checks as guest if it isn't logged in properly */
3449 if (flags
& AS_USER
)
3452 /* does it need write permission? */
3453 if ((flags
& NEED_WRITE
) && !CAN_WRITE(cnum
))
3454 return(ERROR(ERRSRV
,ERRaccess
));
3456 /* ipc services are limited */
3457 if (IS_IPC(cnum
) && (flags
& AS_USER
) && !(flags
& CAN_IPC
))
3458 return(ERROR(ERRSRV
,ERRaccess
));
3460 /* load service specific parameters */
3461 if (OPEN_CNUM(cnum
) && !become_service(cnum
,(flags
& AS_USER
)?True
:False
))
3462 return(ERROR(ERRSRV
,ERRaccess
));
3464 /* does this protocol need to be run as guest? */
3465 if ((flags
& AS_GUEST
) && (!become_guest() || !check_access(-1)))
3466 return(ERROR(ERRSRV
,ERRaccess
));
3470 outsize
= smb_messages
[match
].fn(inbuf
,outbuf
,size
,bufsize
);
3474 outsize
= reply_unknown(inbuf
,outbuf
);
3479 GetTimeOfDay(&msg_end_time
);
3480 if (!(smb_messages
[match
].flags
& TIME_INIT
))
3482 smb_messages
[match
].time
= 0;
3483 smb_messages
[match
].flags
|= TIME_INIT
;
3486 unsigned long this_time
=
3487 (msg_end_time
.tv_sec
- msg_start_time
.tv_sec
)*1e6
+
3488 (msg_end_time
.tv_usec
- msg_start_time
.tv_usec
);
3489 smb_messages
[match
].time
+= this_time
;
3490 total_time
+= this_time
;
3492 DEBUG(2,("TIME %s %d usecs %g pct\n",
3493 smb_fn_name(type
),smb_messages
[match
].time
,
3494 (100.0*smb_messages
[match
].time
) / total_time
));
3501 /****************************************************************************
3502 construct a chained reply and add it to the already made reply
3503 **************************************************************************/
3504 int chain_reply(char *inbuf
,char *outbuf
,int size
,int bufsize
)
3506 static char *orig_inbuf
;
3507 static char *orig_outbuf
;
3508 int smb_com1
, smb_com2
= CVAL(inbuf
,smb_vwv0
);
3509 unsigned smb_off2
= SVAL(inbuf
,smb_vwv1
);
3510 char *inbuf2
, *outbuf2
;
3512 char inbuf_saved
[smb_wct
];
3513 char outbuf_saved
[smb_wct
];
3514 extern int chain_size
;
3515 int wct
= CVAL(outbuf
,smb_wct
);
3516 int outsize
= smb_size
+ 2*wct
+ SVAL(outbuf
,smb_vwv0
+2*wct
);
3518 /* maybe its not chained */
3519 if (smb_com2
== 0xFF) {
3520 CVAL(outbuf
,smb_vwv0
) = 0xFF;
3524 if (chain_size
== 0) {
3525 /* this is the first part of the chain */
3527 orig_outbuf
= outbuf
;
3530 /* we need to tell the client where the next part of the reply will be */
3531 SSVAL(outbuf
,smb_vwv1
,smb_offset(outbuf
+outsize
,outbuf
));
3532 CVAL(outbuf
,smb_vwv0
) = smb_com2
;
3534 /* remember how much the caller added to the chain, only counting stuff
3535 after the parameter words */
3536 chain_size
+= outsize
- smb_wct
;
3538 /* work out pointers into the original packets. The
3539 headers on these need to be filled in */
3540 inbuf2
= orig_inbuf
+ smb_off2
+ 4 - smb_wct
;
3541 outbuf2
= orig_outbuf
+ SVAL(outbuf
,smb_vwv1
) + 4 - smb_wct
;
3543 /* remember the original command type */
3544 smb_com1
= CVAL(orig_inbuf
,smb_com
);
3546 /* save the data which will be overwritten by the new headers */
3547 memcpy(inbuf_saved
,inbuf2
,smb_wct
);
3548 memcpy(outbuf_saved
,outbuf2
,smb_wct
);
3550 /* give the new packet the same header as the last part of the SMB */
3551 memmove(inbuf2
,inbuf
,smb_wct
);
3553 /* create the in buffer */
3554 CVAL(inbuf2
,smb_com
) = smb_com2
;
3556 /* create the out buffer */
3557 bzero(outbuf2
,smb_size
);
3558 set_message(outbuf2
,0,0,True
);
3559 CVAL(outbuf2
,smb_com
) = CVAL(inbuf2
,smb_com
);
3561 memcpy(outbuf2
+4,inbuf2
+4,4);
3562 CVAL(outbuf2
,smb_rcls
) = SUCCESS
;
3563 CVAL(outbuf2
,smb_reh
) = 0;
3564 CVAL(outbuf2
,smb_flg
) = 0x80 | (CVAL(inbuf2
,smb_flg
) & 0x8); /* bit 7 set
3566 SSVAL(outbuf2
,smb_flg2
,1); /* say we support long filenames */
3567 SSVAL(outbuf2
,smb_err
,SUCCESS
);
3568 SSVAL(outbuf2
,smb_tid
,SVAL(inbuf2
,smb_tid
));
3569 SSVAL(outbuf2
,smb_pid
,SVAL(inbuf2
,smb_pid
));
3570 SSVAL(outbuf2
,smb_uid
,SVAL(inbuf2
,smb_uid
));
3571 SSVAL(outbuf2
,smb_mid
,SVAL(inbuf2
,smb_mid
));
3573 DEBUG(3,("Chained message\n"));
3576 /* process the request */
3577 outsize2
= switch_message(smb_com2
,inbuf2
,outbuf2
,size
-chain_size
,
3578 bufsize
-chain_size
);
3580 /* copy the new reply and request headers over the old ones, but
3581 preserve the smb_com field */
3582 memmove(orig_outbuf
,outbuf2
,smb_wct
);
3583 CVAL(orig_outbuf
,smb_com
) = smb_com1
;
3585 /* restore the saved data, being careful not to overwrite any
3586 data from the reply header */
3587 memcpy(inbuf2
,inbuf_saved
,smb_wct
);
3589 int ofs
= smb_wct
- PTR_DIFF(outbuf2
,orig_outbuf
);
3590 if (ofs
< 0) ofs
= 0;
3591 memmove(outbuf2
+ofs
,outbuf_saved
+ofs
,smb_wct
-ofs
);
3599 /****************************************************************************
3600 construct a reply to the incoming packet
3601 ****************************************************************************/
3602 int construct_reply(char *inbuf
,char *outbuf
,int size
,int bufsize
)
3604 int type
= CVAL(inbuf
,smb_com
);
3606 int msg_type
= CVAL(inbuf
,0);
3607 extern int chain_size
;
3609 smb_last_time
= time(NULL
);
3614 bzero(outbuf
,smb_size
);
3617 return(reply_special(inbuf
,outbuf
));
3619 CVAL(outbuf
,smb_com
) = CVAL(inbuf
,smb_com
);
3620 set_message(outbuf
,0,0,True
);
3622 memcpy(outbuf
+4,inbuf
+4,4);
3623 CVAL(outbuf
,smb_rcls
) = SUCCESS
;
3624 CVAL(outbuf
,smb_reh
) = 0;
3625 CVAL(outbuf
,smb_flg
) = 0x80 | (CVAL(inbuf
,smb_flg
) & 0x8); /* bit 7 set
3627 SSVAL(outbuf
,smb_flg2
,1); /* say we support long filenames */
3628 SSVAL(outbuf
,smb_err
,SUCCESS
);
3629 SSVAL(outbuf
,smb_tid
,SVAL(inbuf
,smb_tid
));
3630 SSVAL(outbuf
,smb_pid
,SVAL(inbuf
,smb_pid
));
3631 SSVAL(outbuf
,smb_uid
,SVAL(inbuf
,smb_uid
));
3632 SSVAL(outbuf
,smb_mid
,SVAL(inbuf
,smb_mid
));
3634 outsize
= switch_message(type
,inbuf
,outbuf
,size
,bufsize
);
3636 outsize
+= chain_size
;
3639 smb_setlen(outbuf
,outsize
- 4);
3644 /****************************************************************************
3645 process commands from the client
3646 ****************************************************************************/
3647 static void process(void)
3649 static int trans_num
= 0;
3653 InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3654 OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3655 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
3658 InBuffer
+= SMB_ALIGNMENT
;
3659 OutBuffer
+= SMB_ALIGNMENT
;
3662 DEBUG(3,("priming nmbd\n"));
3665 ip
= *interpret_addr2("localhost");
3666 if (zero_ip(ip
)) ip
= *interpret_addr2("127.0.0.1");
3668 send_one_packet(OutBuffer
,1,ip
,NMB_PORT
,SOCK_DGRAM
);
3678 int deadtime
= lp_deadtime()*60;
3680 int last_keepalive
=0;
3683 deadtime
= DEFAULT_SMBD_TIMEOUT
;
3685 if (lp_readprediction())
3686 do_read_prediction();
3689 extern pstring share_del_pending
;
3690 if (*share_del_pending
) {
3692 if (!unlink(share_del_pending
))
3693 DEBUG(3,("Share file deleted %s\n",share_del_pending
));
3695 DEBUG(2,("Share del failed of %s\n",share_del_pending
));
3696 share_del_pending
[0] = 0;
3700 if (share_mode_pending
) {
3702 check_share_modes();
3703 share_mode_pending
=False
;
3708 for (counter
=SMBD_SELECT_LOOP
;
3709 !receive_smb(Client
,InBuffer
,SMBD_SELECT_LOOP
*1000);
3710 counter
+= SMBD_SELECT_LOOP
)
3714 BOOL allidle
= True
;
3715 extern int keepalive
;
3717 if (smb_read_error
== READ_EOF
) {
3718 DEBUG(3,("end of file from client\n"));
3722 if (smb_read_error
== READ_ERROR
) {
3723 DEBUG(3,("receive_smb error (%s) exiting\n",
3730 /* become root again if waiting */
3733 /* check for smb.conf reload */
3734 if (!(counter
%SMBD_RELOAD_CHECK
))
3735 reload_services(True
);
3737 /* check the share modes every 10 secs */
3738 if (!(counter
%SHARE_MODES_CHECK
))
3739 check_share_modes();
3741 /* clean the share modes every 5 minutes */
3742 if (!(counter
%SHARE_MODES_CLEAN
))
3743 clean_share_modes();
3745 /* automatic timeout if all connections are closed */
3746 if (num_connections_open
==0 && counter
>= IDLE_CLOSED_TIMEOUT
) {
3747 DEBUG(2,("%s Closing idle connection\n",timestring()));
3751 if (keepalive
&& (counter
-last_keepalive
)>keepalive
) {
3752 extern int password_client
;
3753 if (!send_keepalive(Client
)) {
3754 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3757 /* also send a keepalive to the password server if its still
3759 if (password_client
!= -1)
3760 send_keepalive(password_client
);
3761 last_keepalive
= counter
;
3764 /* check for connection timeouts */
3765 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
3766 if (Connections
[i
].open
)
3768 /* close dirptrs on connections that are idle */
3769 if ((t
-Connections
[i
].lastused
)>DPTR_IDLE_TIMEOUT
)
3772 if (Connections
[i
].num_files_open
> 0 ||
3773 (t
-Connections
[i
].lastused
)<deadtime
)
3777 if (allidle
&& num_connections_open
>0) {
3778 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
3783 msg_type
= CVAL(InBuffer
,0);
3784 msg_flags
= CVAL(InBuffer
,1);
3785 type
= CVAL(InBuffer
,smb_com
);
3787 len
= smb_len(InBuffer
);
3789 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type
,len
));
3793 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num
,nread
));
3796 if(trans_num
== 1 && VT_Check(InBuffer
)) {
3806 nread
= construct_reply(InBuffer
,OutBuffer
,nread
,maxxmit
);
3809 if (CVAL(OutBuffer
,0) == 0)
3810 show_msg(OutBuffer
);
3812 if (nread
!= smb_len(OutBuffer
) + 4)
3814 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
3816 smb_len(OutBuffer
)));
3819 send_smb(Client
,OutBuffer
);
3826 /****************************************************************************
3827 initialise connect, service and file structs
3828 ****************************************************************************/
3829 static void init_structs(void )
3832 get_myname(myhostname
,NULL
);
3834 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
3836 Connections
[i
].open
= False
;
3837 Connections
[i
].num_files_open
=0;
3838 Connections
[i
].lastused
=0;
3839 Connections
[i
].used
=False
;
3840 string_init(&Connections
[i
].user
,"");
3841 string_init(&Connections
[i
].dirpath
,"");
3842 string_init(&Connections
[i
].connectpath
,"");
3843 string_init(&Connections
[i
].origpath
,"");
3846 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
3848 Files
[i
].open
= False
;
3849 string_init(&Files
[i
].name
,"");
3853 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
3855 file_fd_struct
*fd_ptr
= &FileFd
[i
];
3856 fd_ptr
->ref_count
= 0;
3857 fd_ptr
->dev
= (int32
)-1;
3858 fd_ptr
->inode
= (int32
)-1;
3860 fd_ptr
->fd_readonly
= -1;
3861 fd_ptr
->fd_writeonly
= -1;
3862 fd_ptr
->real_open_flags
= -1;
3868 /****************************************************************************
3869 usage on the program
3870 ****************************************************************************/
3871 static void usage(char *pname
)
3873 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
3875 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname
);
3876 printf("Version %s\n",VERSION
);
3877 printf("\t-D become a daemon\n");
3878 printf("\t-p port listen on the specified port\n");
3879 printf("\t-d debuglevel set the debuglevel\n");
3880 printf("\t-l log basename. Basename for log/debug files\n");
3881 printf("\t-s services file. Filename of services file\n");
3882 printf("\t-P passive only\n");
3883 printf("\t-a overwrite log file, don't append\n");
3888 /****************************************************************************
3890 ****************************************************************************/
3891 int main(int argc
,char *argv
[])
3893 extern BOOL append_log
;
3894 /* shall I run as a daemon */
3895 BOOL is_daemon
= False
;
3896 int port
= SMB_PORT
;
3898 extern char *optarg
;
3899 char pidFile
[100] = { 0 };
3901 #ifdef NEED_AUTH_PARAMETERS
3902 set_auth_parameters(argc
,argv
);
3913 strcpy(debugf
,SMBLOGFILE
);
3915 setup_logging(argv
[0],False
);
3917 charset_initialise();
3919 /* make absolutely sure we run as root - to handle cases whre people
3920 are crazy enough to have it setuid */
3930 fault_setup(exit_server
);
3931 signal(SIGTERM
, SIGNAL_CAST dflt_sig
);
3933 /* we want total control over the permissions on created files,
3934 so set our umask to 0 */
3941 /* this is for people who can't start the program correctly */
3942 while (argc
> 1 && (*argv
[1] != '-'))
3948 while ((opt
= getopt(argc
, argv
, "O:i:l:s:d:Dp:hPaf:")) != EOF
)
3952 strncpy(pidFile
, optarg
, sizeof(pidFile
));
3955 strcpy(user_socket_options
,optarg
);
3958 strcpy(scope
,optarg
);
3962 extern BOOL passive
;
3967 strcpy(servicesf
,optarg
);
3970 strcpy(debugf
,optarg
);
3974 extern BOOL append_log
;
3975 append_log
= !append_log
;
3985 DEBUGLEVEL
= atoi(optarg
);
3988 port
= atoi(optarg
);
4001 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION
));
4002 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4004 #ifndef NO_GETRLIMIT
4005 #ifdef RLIMIT_NOFILE
4008 getrlimit(RLIMIT_NOFILE
, &rlp
);
4009 rlp
.rlim_cur
= (MAX_OPEN_FILES
>rlp
.rlim_max
)? rlp
.rlim_max
:MAX_OPEN_FILES
;
4010 setrlimit(RLIMIT_NOFILE
, &rlp
);
4011 getrlimit(RLIMIT_NOFILE
, &rlp
);
4012 DEBUG(3,("Maximum number of open files per session is %d\n",rlp
.rlim_cur
));
4018 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4019 getuid(),getgid(),geteuid(),getegid()));
4021 if (sizeof(uint16
) < 2 || sizeof(uint32
) < 4)
4023 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4029 if (!reload_services(False
))
4032 #ifndef NO_SIGNAL_TEST
4033 signal(SIGHUP
,SIGNAL_CAST sig_hup
);
4036 DEBUG(3,("%s loaded services\n",timestring()));
4038 if (!is_daemon
&& !is_a_socket(0))
4040 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4046 DEBUG(3,("%s becoming a daemon\n",timestring()));
4055 if ((fd
= open(pidFile
,
4056 O_NONBLOCK
| O_CREAT
| O_WRONLY
| O_TRUNC
, 0644)) < 0)
4058 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile
, strerror(errno
)));
4061 if(fcntl_lock(fd
,F_SETLK
,0,1,F_WRLCK
)==False
)
4063 DEBUG(0,("ERROR: smbd is already running\n"));
4066 sprintf(buf
, "%u\n", (unsigned int) getpid());
4067 if (write(fd
, buf
, strlen(buf
)) < 0)
4069 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile
, strerror(errno
)));
4072 /* Leave pid file open & locked for the duration... */
4075 if (!open_sockets(is_daemon
,port
))
4078 #if FAST_SHARE_MODES
4079 if (!start_share_mode_mgmt())
4083 /* possibly reload the services file. */
4084 reload_services(True
);
4086 maxxmit
= MIN(lp_maxxmit(),BUFFER_SIZE
);
4090 if (sys_chroot(lp_rootdir()) == 0)
4091 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4097 exit_server("normal exit");