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.
28 pstring servicesf
= CONFIGFILE
;
29 pstring OriginalDir
="/";
30 extern pstring debugf
;
31 extern pstring sesssetup_user
;
33 char *InBuffer
= NULL
;
34 char *OutBuffer
= NULL
;
35 char *last_inbuf
= NULL
;
40 BOOL share_mode_pending
= False
;
42 /* have I done a become_user? */
47 /* the last message the was processed */
48 int last_message
= -1;
50 /* a useful macro to debug the last message processed */
51 #define LAST_MESSAGE() smb_fn_name(last_message)
54 extern int DEBUGLEVEL
;
55 extern int case_default
;
56 extern BOOL case_sensitive
;
57 extern BOOL case_preserve
;
58 extern BOOL use_mangled_map
;
59 extern BOOL short_case_preserve
;
60 extern BOOL case_mangle
;
61 extern time_t smb_last_time
;
63 extern pstring user_socket_options
;
65 connection_struct Connections
[MAX_CONNECTIONS
];
66 files_struct Files
[MAX_OPEN_FILES
];
70 int maxxmit
= BUFFER_SIZE
;
74 /* a fnum to use when chaining */
77 /* number of open connections */
78 static int num_connections_open
= 0;
80 extern fstring remote_machine
;
83 /* these can be set by some functions to override the error codes */
84 int unix_ERR_class
=SUCCESS
;
88 extern int extra_time_offset
;
90 extern pstring myhostname
;
91 extern struct in_addr myip
;
94 static int find_free_connection(int hash
);
97 extern void generate_next_challenge(char *challenge
);
98 extern void set_challenge(char *challenge
);
101 /* for readability... */
102 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
103 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
104 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
105 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
106 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
110 /****************************************************************************
111 change a dos mode to a unix mode
112 base permission for files:
113 everybody gets read bit set
114 dos readonly is represented in unix by removing everyone's write bit
115 dos archive is represented in unix by the user's execute bit
116 dos system is represented in unix by the group's execute bit
117 dos hidden is represented in unix by the other's execute bit
118 base permission for directories:
119 dos directory is represented in unix by unix's dir bit and the exec bit
120 ****************************************************************************/
121 mode_t
unix_mode(int cnum
,int dosmode
)
123 mode_t result
= (S_IRUSR
| S_IRGRP
| S_IROTH
);
125 if ( !IS_DOS_READONLY(dosmode
) )
126 result
|= (S_IWUSR
| S_IWGRP
| S_IWOTH
);
128 if (IS_DOS_DIR(dosmode
))
129 result
|= (S_IFDIR
| S_IXUSR
| S_IXGRP
| S_IXOTH
| S_IWUSR
);
131 if (MAP_ARCHIVE(cnum
) && IS_DOS_ARCHIVE(dosmode
))
134 if (MAP_SYSTEM(cnum
) && IS_DOS_SYSTEM(dosmode
))
137 if (MAP_HIDDEN(cnum
) && IS_DOS_HIDDEN(dosmode
))
140 result
&= CREATE_MODE(cnum
);
145 /****************************************************************************
146 change a unix mode to a dos mode
147 ****************************************************************************/
148 int dos_mode(int cnum
,char *path
,struct stat
*sbuf
)
153 if (!CAN_WRITE(cnum
) || !((sbuf
->st_mode
& S_IWOTH
) ||
154 Connections
[cnum
].admin_user
||
155 ((sbuf
->st_mode
& S_IWUSR
) &&
156 Connections
[cnum
].uid
==sbuf
->st_uid
) ||
157 ((sbuf
->st_mode
& S_IWGRP
) &&
158 in_group(sbuf
->st_gid
,Connections
[cnum
].gid
,
159 Connections
[cnum
].ngroups
,
160 Connections
[cnum
].igroups
))))
163 if (CAN_WRITE(cnum
) && !lp_alternate_permissions(SNUM(cnum
))) {
164 if (!((sbuf
->st_mode
& S_IWOTH
) ||
165 Connections
[cnum
].admin_user
||
166 ((sbuf
->st_mode
& S_IWUSR
) && Connections
[cnum
].uid
==sbuf
->st_uid
) ||
167 ((sbuf
->st_mode
& S_IWGRP
) &&
168 in_group(sbuf
->st_gid
,Connections
[cnum
].gid
,
169 Connections
[cnum
].ngroups
,Connections
[cnum
].igroups
))))
172 if ((sbuf
->st_mode
& S_IWUSR
) == 0)
177 if ((sbuf
->st_mode
& S_IXUSR
) != 0)
180 if (MAP_SYSTEM(cnum
) && ((sbuf
->st_mode
& S_IXGRP
) != 0))
183 if (MAP_HIDDEN(cnum
) && ((sbuf
->st_mode
& S_IXOTH
) != 0))
186 if (S_ISDIR(sbuf
->st_mode
))
187 result
= aDIR
| (result
& aRONLY
);
190 if (S_ISLNK(sbuf
->st_mode
) && S_ISDIR(sbuf
->st_mode
))
194 /* hide files with a name starting with a . */
195 if (lp_hide_dot_files(SNUM(cnum
)))
197 char *p
= strrchr(path
,'/');
203 if (p
[0] == '.' && p
[1] != '.' && p
[1] != 0)
211 /*******************************************************************
212 chmod a file - but preserve some bits
213 ********************************************************************/
214 int dos_chmod(int cnum
,char *fname
,int dosmode
,struct stat
*st
)
223 if (sys_stat(fname
,st
)) return(-1);
226 if (S_ISDIR(st
->st_mode
)) dosmode
|= aDIR
;
228 if (dos_mode(cnum
,fname
,st
) == dosmode
) return(0);
230 unixmode
= unix_mode(cnum
,dosmode
);
232 /* preserve the s bits */
233 mask
|= (S_ISUID
| S_ISGID
);
235 /* preserve the t bit */
240 /* possibly preserve the x bits */
241 if (!MAP_ARCHIVE(cnum
)) mask
|= S_IXUSR
;
242 if (!MAP_SYSTEM(cnum
)) mask
|= S_IXGRP
;
243 if (!MAP_HIDDEN(cnum
)) mask
|= S_IXOTH
;
245 unixmode
|= (st
->st_mode
& mask
);
247 /* if we previously had any r bits set then leave them alone */
248 if ((tmp
= st
->st_mode
& (S_IRUSR
|S_IRGRP
|S_IROTH
))) {
249 unixmode
&= ~(S_IRUSR
|S_IRGRP
|S_IROTH
);
253 /* if we previously had any w bits set then leave them alone
254 if the new mode is not rdonly */
255 if (!IS_DOS_READONLY(dosmode
) &&
256 (tmp
= st
->st_mode
& (S_IWUSR
|S_IWGRP
|S_IWOTH
))) {
257 unixmode
&= ~(S_IWUSR
|S_IWGRP
|S_IWOTH
);
261 return(chmod(fname
,unixmode
));
265 /****************************************************************************
266 check if two filenames are equal
268 this needs to be careful about whether we are case sensitive
269 ****************************************************************************/
270 static BOOL
fname_equal(char *name1
, char *name2
)
272 int l1
= strlen(name1
);
273 int l2
= strlen(name2
);
275 /* handle filenames ending in a single dot */
276 if (l1
-l2
== 1 && name1
[l1
-1] == '.' && lp_strip_dot())
280 ret
= fname_equal(name1
,name2
);
285 if (l2
-l1
== 1 && name2
[l2
-1] == '.' && lp_strip_dot())
289 ret
= fname_equal(name1
,name2
);
294 /* now normal filename handling */
296 return(strcmp(name1
,name2
) == 0);
298 return(strequal(name1
,name2
));
302 /****************************************************************************
303 mangle the 2nd name and check if it is then equal to the first name
304 ****************************************************************************/
305 static BOOL
mangled_equal(char *name1
, char *name2
)
312 strcpy(tmpname
,name2
);
313 mangle_name_83(tmpname
);
315 return(strequal(name1
,tmpname
));
319 /****************************************************************************
320 scan a directory to find a filename, matching without case sensitivity
322 If the name looks like a mangled name then try via the mangling functions
323 ****************************************************************************/
324 static BOOL
scan_directory(char *path
, char *name
,int snum
,BOOL docache
)
331 mangled
= is_mangled(name
);
333 /* handle null paths */
337 if (docache
&& (dname
= DirCacheCheck(path
,name
,snum
))) {
343 check_mangled_stack(name
);
345 /* open the directory */
346 if (!(cur_dir
= OpenDir(path
)))
348 DEBUG(3,("scan dir didn't open dir [%s]\n",path
));
352 /* now scan for matching names */
353 while ((dname
= ReadDirName(cur_dir
)))
356 (strequal(dname
,".") || strequal(dname
,"..")))
360 if (!name_map_mangle(name2
,False
,snum
)) continue;
362 if ((mangled
&& mangled_equal(name
,name2
))
363 || fname_equal(name
, name2
))
365 /* we've found the file, change it's name and return */
366 if (docache
) DirCacheAdd(path
,name
,dname
,snum
);
377 /****************************************************************************
378 This routine is called to convert names from the dos namespace to unix
379 namespace. It needs to handle any case conversions, mangling, format
382 We assume that we have already done a chdir() to the right "root" directory
385 The function will return False if some part of the name except for the last
386 part cannot be resolved
387 ****************************************************************************/
388 BOOL
unix_convert(char *name
,int cnum
)
396 /* convert to basic unix format - removing \ chars and cleaning it up */
398 unix_clean_name(name
);
400 if (!case_sensitive
&&
401 (!case_preserve
|| (is_8_3(name
) && !short_case_preserve
)))
404 /* names must be relative to the root of the service - trim any leading /.
405 also trim trailing /'s */
406 trim_string(name
,"/","/");
408 /* check if it's a printer file */
409 if (Connections
[cnum
].printer
)
411 if ((! *name
) || strchr(name
,'/') || !is_8_3(name
))
414 sprintf(name2
,"%.6s.XXXXXX",remote_machine
);
415 strcpy(name
,(char *)mktemp(name2
));
420 /* stat the name - if it exists then we are all done! */
421 if (sys_stat(name
,&st
) == 0)
424 DEBUG(5,("unix_convert(%s,%d)\n",name
,cnum
));
426 /* a special case - if we don't have any mangling chars and are case
427 sensitive then searching won't help */
428 if (case_sensitive
&& !is_mangled(name
) &&
429 !lp_strip_dot() && !use_mangled_map
)
432 /* now we need to recursively match the name against the real
433 directory structure */
436 while (strncmp(start
,"./",2) == 0)
439 /* now match each part of the path name separately, trying the names
440 as is first, then trying to scan the directory for matching names */
441 for (;start
;start
= (end
?end
+1:(char *)NULL
))
443 /* pinpoint the end of this section of the filename */
444 end
= strchr(start
, '/');
446 /* chop the name at this point */
449 /* check if the name exists up to this point */
450 if (sys_stat(name
, &st
) == 0)
452 /* it exists. it must either be a directory or this must be
453 the last part of the path for it to be OK */
454 if (end
&& !(st
.st_mode
& S_IFDIR
))
456 /* an intermediate part of the name isn't a directory */
457 DEBUG(5,("Not a dir %s\n",start
));
468 /* remember the rest of the pathname so it can be restored
470 if (end
) strcpy(rest
,end
+1);
473 /* try to find this part of the path in the directory */
474 if (strchr(start
,'?') || strchr(start
,'*') ||
475 !scan_directory(dirpath
, start
, SNUM(cnum
), end
?True
:False
))
479 /* an intermediate part of the name can't be found */
480 DEBUG(5,("Intermediate not found %s\n",start
));
485 /* just the last part of the name doesn't exist */
486 /* we may need to strupper() or strlower() it in case
487 this conversion is being used for file creation
489 /* if the filename is of mixed case then don't normalise it */
490 if (!case_preserve
&&
491 (!strhasupper(start
) || !strhaslower(start
)))
494 /* check on the mangled stack to see if we can recover the
495 base of the filename */
496 if (is_mangled(start
))
497 check_mangled_stack(start
);
499 DEBUG(5,("New file %s\n",start
));
503 /* restore the rest of the string */
506 strcpy(start
+strlen(start
)+1,rest
);
507 end
= start
+ strlen(start
);
511 /* add to the dirpath that we have resolved so far */
512 if (*dirpath
) strcat(dirpath
,"/");
513 strcat(dirpath
,start
);
515 /* restore the / that we wiped out earlier */
519 /* the name has been resolved */
520 DEBUG(5,("conversion finished %s\n",name
));
529 /****************************************************************************
530 try to get the disk space from disk quotas (LINUX version)
531 ****************************************************************************/
533 If you didn't make the symlink to the quota package, too bad :(
535 #include "quota/quotactl.c"
536 #include "quota/hasquota.c"
537 static BOOL
disk_quotas(char *path
, int *bsize
, int *dfree
, int *dsize
)
549 /* find the block device file */
551 if ( stat(path
, &S
) == -1 )
556 fp
= setmntent(MOUNTED
,"r");
559 while ((mnt
= getmntent(fp
)) != (struct mntent
*) 0) {
560 if ( stat(mnt
->mnt_dir
,&S
) == -1 )
562 if (S
.st_dev
== devno
) {
572 qcmd
= QCMD(Q_GETQUOTA
, USRQUOTA
);
574 if (hasmntopt(mnt
, MNTOPT_NOAUTO
) || hasmntopt(mnt
, MNTOPT_NOQUOTA
))
577 if (!hasquota(mnt
, USRQUOTA
, &qfpathname
))
580 euser_id
= geteuid();
583 if (quotactl(qcmd
, mnt
->mnt_fsname
, euser_id
, (caddr_t
)&D
) != 0) {
584 if ((fd
= open(qfpathname
, O_RDONLY
)) < 0) {
588 lseek(fd
, (long) dqoff(euser_id
), L_SET
);
589 switch (read(fd
, &D
, sizeof(struct dqblk
))) {
591 memset((caddr_t
)&D
, 0, sizeof(struct dqblk
));
593 case sizeof(struct dqblk
): /* OK */
604 if (D
.dqb_bsoftlimit
==0)
606 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)||(D
.dqb_curinodes
>D
.dqb_isoftlimit
))
609 *dsize
= D
.dqb_curblocks
;
612 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
613 *dsize
= D
.dqb_bsoftlimit
;
619 /****************************************************************************
620 try to get the disk space from disk quotas
621 ****************************************************************************/
622 static BOOL
disk_quotas(char *path
, int *bsize
, int *dfree
, int *dsize
)
624 uid_t user_id
, euser_id
;
629 /* find the block device file */
630 if ((stat(path
, &S
)<0) ||
631 (devnm(S_IFBLK
, S
.st_dev
, dev_disk
, 256, 0)<0)) return (False
);
633 euser_id
= geteuid();
636 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
638 setresuid(euser_id
,-1,-1);
640 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
642 if (setresuid(user_id
,-1,-1))
643 DEBUG(5,("Unable to reset uid to %d\n", user_id
));
645 /* Use softlimit to determine disk space, except when it has been exceeded */
652 *dsize
=D
.dqb_curblocks
;
657 /* Use softlimit to determine disk space, except when it has been exceeded */
658 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)||(D
.dqb_curfiles
>D
.dqb_fsoftlimit
))
661 *dsize
= D
.dqb_curblocks
;
664 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
665 *dsize
= D
.dqb_bsoftlimit
;
670 /****************************************************************************
671 try to get the disk space from disk quotas (CRAY VERSION)
672 ****************************************************************************/
673 static BOOL
disk_quotas(char *path
, int *bsize
, int *dfree
, int *dsize
)
679 static dev_t devno_cached
= 0 ;
680 static char name
[MNTMAXSTR
] ;
681 struct q_request request
;
682 struct qf_header header
;
683 static int quota_default
= 0 ;
686 if ( stat(path
,&sbuf
) == -1 )
689 devno
= sbuf
.st_dev
;
691 if ( devno
!= devno_cached
) {
693 devno_cached
= devno
;
695 if ((fd
= setmntent(KMTAB
)) == NULL
)
700 while ((mnt
= getmntent(fd
)) != NULL
) {
702 if ( stat(mnt
->mnt_dir
,&sbuf
) == -1 )
705 if (sbuf
.st_dev
== devno
) {
714 strcpy(name
,mnt
->mnt_dir
) ;
721 request
.qf_magic
= QF_MAGIC
;
722 request
.qf_entry
.id
= geteuid() ;
724 if (quotactl(name
, Q_GETQUOTA
, &request
) == -1)
727 if ( ! request
.user
)
730 if ( request
.qf_entry
.user_q
.f_quota
== QFV_DEFAULT
) {
732 if ( ! quota_default
) {
734 if ( quotactl(name
, Q_GETHEADER
, &header
) == -1 )
737 quota_default
= header
.user_h
.def_fq
;
740 *dfree
= quota_default
;
742 }else if ( request
.qf_entry
.user_q
.f_quota
== QFV_PREVENT
) {
748 *dfree
= request
.qf_entry
.user_q
.f_quota
;
752 *dsize
= request
.qf_entry
.user_q
.f_use
;
760 *bsize
= 4096 ; /* Cray blocksize */
770 /****************************************************************************
771 normalise for DOS usage
772 ****************************************************************************/
773 static void disk_norm(int *bsize
,int *dfree
,int *dsize
)
775 /* check if the disk is beyond the max disk size */
776 int maxdisksize
= lp_maxdisksize();
778 /* convert to blocks - and don't overflow */
779 maxdisksize
= ((maxdisksize
*1024)/(*bsize
))*1024;
780 if (*dsize
> maxdisksize
) *dsize
= maxdisksize
;
781 if (*dfree
> maxdisksize
) *dfree
= maxdisksize
-1; /* the -1 should stop
786 while (*dfree
> WORDMAX
|| *dsize
> WORDMAX
|| *bsize
< 512)
791 if (*bsize
> WORDMAX
)
794 if (*dsize
> WORDMAX
)
796 if (*dfree
> WORDMAX
)
803 /****************************************************************************
804 return number of 1K blocks available on a path and total number
805 ****************************************************************************/
806 int disk_free(char *path
,int *bsize
,int *dfree
,int *dsize
)
808 char *df_command
= lp_dfree_command();
822 if (disk_quotas(path
, bsize
, dfree
, dsize
))
824 disk_norm(bsize
,dfree
,dsize
);
825 return(((*bsize
)/1024)*(*dfree
));
830 /* possibly use system() to get the result */
831 if (df_command
&& *df_command
)
837 sprintf(outfile
,"/tmp/dfree.smb.%d",(int)getpid());
838 sprintf(syscmd
,"%s %s",df_command
,path
);
839 standard_sub_basic(syscmd
);
841 ret
= smbrun(syscmd
,outfile
);
842 DEBUG(3,("Running the command `%s' gave %d\n",syscmd
,ret
));
845 FILE *f
= fopen(outfile
,"r");
851 fscanf(f
,"%d %d %d",dsize
,dfree
,bsize
);
855 DEBUG(0,("Can't open %s\n",outfile
));
859 disk_norm(bsize
,dfree
,dsize
);
860 return(((*bsize
)/1024)*(*dfree
));
864 DEBUG(1,("Warning - no statfs function\n"));
868 if (statfs(path
,&fs
,sizeof(fs
),0) != 0)
871 if (statvfs(path
, &fs
))
874 if (statfs(path
,&fs
,sizeof(fs
)) == -1)
876 if (statfs(path
,&fs
) == -1)
878 #endif /* USE_STATVFS */
881 DEBUG(3,("dfree call failed code errno=%d\n",errno
));
885 return(((*bsize
)/1024)*(*dfree
));
890 *dfree
= fs
.fd_req
.bfree
;
891 *dsize
= fs
.fd_req
.btot
;
894 *bsize
= fs
.f_frsize
;
897 /* eg: osf1 has f_fsize = fundamental filesystem block size,
898 f_bsize = optimal transfer block size (MX: 94-04-19) */
903 #endif /* USE_STATVFS */
908 *dfree
= fs
.f_bavail
;
910 *dsize
= fs
.f_blocks
;
913 #if defined(SCO) || defined(ISC) || defined(MIPS)
917 /* handle rediculous bsize values - some OSes are broken */
918 if ((*bsize
) < 512 || (*bsize
)>0xFFFF) *bsize
= 1024;
920 disk_norm(bsize
,dfree
,dsize
);
926 DEBUG(0,("dfree seems to be broken on your system\n"));
927 *dsize
= 20*1024*1024/(*bsize
);
928 *dfree
= MAX(1,*dfree
);
930 return(((*bsize
)/1024)*(*dfree
));
935 /****************************************************************************
936 wrap it to get filenames right
937 ****************************************************************************/
938 int sys_disk_free(char *path
,int *bsize
,int *dfree
,int *dsize
)
940 return(disk_free(dos_to_unix(path
,False
),bsize
,dfree
,dsize
));
945 /****************************************************************************
946 check a filename - possibly caling reducename
948 This is called by every routine before it allows an operation on a filename.
949 It does any final confirmation necessary to ensure that the filename is
950 a valid one for the user to access.
951 ****************************************************************************/
952 BOOL
check_name(char *name
,int cnum
)
958 ret
= reduce_name(name
,Connections
[cnum
].connectpath
,lp_widelinks(SNUM(cnum
)));
960 DEBUG(5,("check_name on %s failed\n",name
));
965 /****************************************************************************
966 check a filename - possibly caling reducename
967 ****************************************************************************/
968 static void check_for_pipe(char *fname
)
970 /* special case of pipe opens */
974 if (strstr(s
,"pipe/"))
976 DEBUG(3,("Rejecting named pipe open for %s\n",fname
));
977 unix_ERR_class
= ERRSRV
;
978 unix_ERR_code
= ERRaccess
;
983 /****************************************************************************
985 ****************************************************************************/
986 void open_file(int fnum
,int cnum
,char *fname1
,int flags
,int mode
)
990 Files
[fnum
].open
= False
;
994 strcpy(fname
,fname1
);
996 /* check permissions */
997 if ((flags
!= O_RDONLY
) && !CAN_WRITE(cnum
) && !Connections
[cnum
].printer
)
999 DEBUG(3,("Permission denied opening %s\n",fname
));
1000 check_for_pipe(fname
);
1004 /* this handles a bug in Win95 - it doesn't say to create the file when it
1006 if (Connections
[cnum
].printer
)
1010 if (flags == O_WRONLY)
1011 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
1014 #if UTIME_WORKAROUND
1015 /* XXXX - is this OK?? */
1016 /* this works around a utime bug but can cause other problems */
1017 if ((flags
& (O_WRONLY
|O_RDWR
)) && (flags
& O_CREAT
) && !(flags
& O_APPEND
))
1022 Files
[fnum
].fd
= sys_open(fname
,flags
,mode
);
1024 if ((Files
[fnum
].fd
>=0) &&
1025 Connections
[cnum
].printer
&& lp_minprintspace(SNUM(cnum
))) {
1029 strcpy(dname
,fname
);
1030 p
= strrchr(dname
,'/');
1032 if (sys_disk_free(dname
,&dum1
,&dum2
,&dum3
) <
1033 lp_minprintspace(SNUM(cnum
))) {
1034 close(Files
[fnum
].fd
);
1035 Files
[fnum
].fd
= -1;
1043 /* Fix for files ending in '.' */
1044 if((Files
[fnum
].fd
== -1) && (errno
== ENOENT
) &&
1045 (strchr(fname
,'.')==NULL
))
1048 Files
[fnum
].fd
= sys_open(fname
,flags
,mode
);
1051 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
1052 if ((Files
[fnum
].fd
== -1) && (errno
== ENAMETOOLONG
))
1055 char *p
= strrchr(fname
, '/');
1057 if (p
== fname
) /* name is "/xxx" */
1059 max_len
= pathconf("/", _PC_NAME_MAX
);
1062 else if ((p
== NULL
) || (p
== fname
))
1065 max_len
= pathconf(".", _PC_NAME_MAX
);
1070 max_len
= pathconf(fname
, _PC_NAME_MAX
);
1074 if (strlen(p
) > max_len
)
1076 char tmp
= p
[max_len
];
1079 if ((Files
[fnum
].fd
= sys_open(fname
,flags
,mode
)) == -1)
1085 if (Files
[fnum
].fd
< 0)
1087 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1088 fname
,strerror(errno
),flags
));
1089 check_for_pipe(fname
);
1093 if (Files
[fnum
].fd
>= 0)
1096 Connections
[cnum
].num_files_open
++;
1097 fstat(Files
[fnum
].fd
,&st
);
1098 Files
[fnum
].mode
= st
.st_mode
;
1099 Files
[fnum
].open_time
= time(NULL
);
1100 Files
[fnum
].size
= 0;
1101 Files
[fnum
].pos
= -1;
1102 Files
[fnum
].open
= True
;
1103 Files
[fnum
].mmap_ptr
= NULL
;
1104 Files
[fnum
].mmap_size
= 0;
1105 Files
[fnum
].can_lock
= True
;
1106 Files
[fnum
].can_read
= ((flags
& O_WRONLY
)==0);
1107 Files
[fnum
].can_write
= ((flags
& (O_WRONLY
|O_RDWR
))!=0);
1108 Files
[fnum
].share_mode
= 0;
1109 Files
[fnum
].share_pending
= False
;
1110 Files
[fnum
].print_file
= Connections
[cnum
].printer
;
1111 Files
[fnum
].modified
= False
;
1112 Files
[fnum
].cnum
= cnum
;
1113 string_set(&Files
[fnum
].name
,fname
);
1114 Files
[fnum
].wbmpx_ptr
= NULL
;
1117 * If the printer is marked as postscript output a leading
1118 * file identifier to ensure the file is treated as a raw
1120 * This has a similar effect as CtrlD=0 in WIN.INI file.
1121 * tim@fsg.com 09/06/94
1123 if (Files
[fnum
].print_file
&& POSTSCRIPT(cnum
) &&
1124 Files
[fnum
].can_write
)
1126 DEBUG(3,("Writing postscript line\n"));
1127 write_file(fnum
,"%!\n",3);
1130 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1131 timestring(),Connections
[cnum
].user
,fname
,
1132 BOOLSTR(Files
[fnum
].can_read
),BOOLSTR(Files
[fnum
].can_write
),
1133 Connections
[cnum
].num_files_open
,fnum
));
1138 /* mmap it if read-only */
1139 if (!Files
[fnum
].can_write
)
1141 Files
[fnum
].mmap_size
= file_size(fname
);
1142 Files
[fnum
].mmap_ptr
= (char *)mmap(NULL
,Files
[fnum
].mmap_size
,
1143 PROT_READ
,MAP_SHARED
,Files
[fnum
].fd
,0);
1145 if (Files
[fnum
].mmap_ptr
== (char *)-1 || !Files
[fnum
].mmap_ptr
)
1147 DEBUG(3,("Failed to mmap() %s - %s\n",fname
,strerror(errno
)));
1148 Files
[fnum
].mmap_ptr
= NULL
;
1154 /*******************************************************************
1156 ********************************************************************/
1157 void sync_file(int fnum
)
1160 fsync(Files
[fnum
].fd
);
1164 /****************************************************************************
1165 run a file if it is a magic script
1166 ****************************************************************************/
1167 static void check_magic(int fnum
,int cnum
)
1169 if (!*lp_magicscript(SNUM(cnum
)))
1172 DEBUG(5,("checking magic for %s\n",Files
[fnum
].name
));
1176 if (!(p
= strrchr(Files
[fnum
].name
,'/')))
1177 p
= Files
[fnum
].name
;
1181 if (!strequal(lp_magicscript(SNUM(cnum
)),p
))
1187 pstring magic_output
;
1189 strcpy(fname
,Files
[fnum
].name
);
1191 if (*lp_magicoutput(SNUM(cnum
)))
1192 strcpy(magic_output
,lp_magicoutput(SNUM(cnum
)));
1194 sprintf(magic_output
,"%s.out",fname
);
1197 ret
= smbrun(fname
,magic_output
);
1198 DEBUG(3,("Invoking magic command %s gave %d\n",fname
,ret
));
1204 /****************************************************************************
1205 close a file - possibly invalidating the read prediction
1206 ****************************************************************************/
1207 void close_file(int fnum
)
1209 int cnum
= Files
[fnum
].cnum
;
1210 invalidate_read_prediction(Files
[fnum
].fd
);
1211 Files
[fnum
].open
= False
;
1212 Connections
[cnum
].num_files_open
--;
1213 if(Files
[fnum
].wbmpx_ptr
)
1215 free((char *)Files
[fnum
].wbmpx_ptr
);
1216 Files
[fnum
].wbmpx_ptr
= NULL
;
1220 if(Files
[fnum
].mmap_ptr
)
1222 munmap(Files
[fnum
].mmap_ptr
,Files
[fnum
].mmap_size
);
1223 Files
[fnum
].mmap_ptr
= NULL
;
1227 if (lp_share_modes(SNUM(cnum
)))
1228 del_share_mode(fnum
);
1230 if (Files
[fnum
].modified
) {
1232 if (fstat(Files
[fnum
].fd
,&st
) == 0) {
1233 int dosmode
= dos_mode(cnum
,Files
[fnum
].name
,&st
);
1234 if (!IS_DOS_ARCHIVE(dosmode
)) {
1235 dos_chmod(cnum
,Files
[fnum
].name
,dosmode
| aARCH
,&st
);
1240 close(Files
[fnum
].fd
);
1242 /* NT uses smbclose to start a print - weird */
1243 if (Files
[fnum
].print_file
)
1246 /* check for magic scripts */
1247 check_magic(fnum
,cnum
);
1249 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1250 timestring(),Connections
[cnum
].user
,Files
[fnum
].name
,
1251 Connections
[cnum
].num_files_open
));
1254 enum {AFAIL
,AREAD
,AWRITE
,AALL
};
1256 /*******************************************************************
1257 reproduce the share mode access table
1258 ********************************************************************/
1259 static int access_table(int new_deny
,int old_deny
,int old_mode
,
1260 int share_pid
,char *fname
)
1262 if (new_deny
== DENY_ALL
|| old_deny
== DENY_ALL
) return(AFAIL
);
1264 if (new_deny
== DENY_DOS
|| old_deny
== DENY_DOS
) {
1265 if (old_deny
== new_deny
&& share_pid
== getpid())
1268 if (old_mode
== 0) return(AREAD
);
1270 /* the new smbpub.zip spec says that if the file extension is
1271 .com, .dll, .exe or .sym then allow the open. I will force
1272 it to read-only as this seems sensible although the spec is
1273 a little unclear on this. */
1274 if ((fname
= strrchr(fname
,'.'))) {
1275 if (strequal(fname
,".com") ||
1276 strequal(fname
,".dll") ||
1277 strequal(fname
,".exe") ||
1278 strequal(fname
,".sym"))
1288 if (old_deny
==DENY_WRITE
&& old_mode
==0) return(AREAD
);
1289 if (old_deny
==DENY_READ
&& old_mode
==0) return(AWRITE
);
1290 if (old_deny
==DENY_NONE
&& old_mode
==0) return(AALL
);
1293 if (old_deny
==DENY_WRITE
&& old_mode
==1) return(AREAD
);
1294 if (old_deny
==DENY_READ
&& old_mode
==1) return(AWRITE
);
1295 if (old_deny
==DENY_NONE
&& old_mode
==1) return(AALL
);
1298 if (old_deny
==DENY_WRITE
) return(AREAD
);
1299 if (old_deny
==DENY_READ
) return(AWRITE
);
1300 if (old_deny
==DENY_NONE
) return(AALL
);
1306 /*******************************************************************
1307 check if the share mode on a file allows it to be deleted or unlinked
1308 return True if sharing doesn't prevent the operation
1309 ********************************************************************/
1310 BOOL
check_file_sharing(int cnum
,char *fname
)
1313 int share_mode
= get_share_mode_byname(cnum
,fname
,&pid
);
1315 if (!pid
|| !share_mode
) return(True
);
1317 if (share_mode
== DENY_DOS
)
1318 return(pid
== getpid());
1320 /* XXXX exactly what share mode combinations should be allowed for
1321 deleting/renaming? */
1325 /****************************************************************************
1327 Helper for open_file_shared.
1328 Truncate a file after checking locking; close file if locked.
1329 **************************************************************************/
1330 static void truncate_unless_locked(int fnum
, int cnum
)
1332 if (Files
[fnum
].can_write
){
1333 if (is_locked(fnum
,cnum
,0x3FFFFFFF,0)){
1336 unix_ERR_class
= ERRDOS
;
1337 unix_ERR_code
= ERRlock
;
1340 ftruncate(Files
[fnum
].fd
,0);
1345 /****************************************************************************
1346 open a file with a share mode
1347 ****************************************************************************/
1348 void open_file_shared(int fnum
,int cnum
,char *fname
,int share_mode
,int ofun
,
1349 int mode
,int *Access
,int *action
)
1353 int deny_mode
= (share_mode
>>4)&7;
1355 BOOL file_existed
= file_exist(fname
,&sbuf
);
1356 BOOL fcbopen
= False
;
1359 Files
[fnum
].open
= False
;
1360 Files
[fnum
].fd
= -1;
1362 /* this is for OS/2 EAs - try and say we don't support them */
1363 if (strstr(fname
,".+,;=[].")) {
1364 unix_ERR_class
= ERRDOS
;
1365 unix_ERR_code
= ERROR_EAS_NOT_SUPPORTED
;
1369 if ((ofun
& 0x3) == 0 && file_existed
) {
1376 if ((ofun
& 0x3) == 2)
1379 /* note that we ignore the append flag as
1380 append does not mean the same thing under dos and unix */
1382 switch (share_mode
&0xF)
1399 if (flags
!= O_RDONLY
&& file_existed
&&
1400 (!CAN_WRITE(cnum
) || IS_DOS_READONLY(dos_mode(cnum
,fname
,&sbuf
)))) {
1408 if (deny_mode
> DENY_NONE
&& deny_mode
!=DENY_FCB
) {
1409 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode
,fname
));
1414 if (deny_mode
== DENY_FCB
) deny_mode
= DENY_DOS
;
1416 if (lp_share_modes(SNUM(cnum
))) {
1420 old_share
= get_share_mode(cnum
,&sbuf
,&share_pid
);
1423 /* someone else has a share lock on it, check to see
1425 int old_open_mode
= old_share
&0xF;
1426 int old_deny_mode
= (old_share
>>4)&7;
1428 if (deny_mode
> 4 || old_deny_mode
> 4 || old_open_mode
> 2) {
1429 DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1430 deny_mode
,old_deny_mode
,old_open_mode
,fname
));
1432 unix_ERR_class
= ERRDOS
;
1433 unix_ERR_code
= ERRbadshare
;
1438 int access_allowed
= access_table(deny_mode
,old_deny_mode
,old_open_mode
,
1441 if ((access_allowed
== AFAIL
) ||
1442 (access_allowed
== AREAD
&& flags
== O_WRONLY
) ||
1443 (access_allowed
== AWRITE
&& flags
== O_RDONLY
)) {
1444 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1445 deny_mode
,old_deny_mode
,old_open_mode
,
1449 unix_ERR_class
= ERRDOS
;
1450 unix_ERR_code
= ERRbadshare
;
1454 if (access_allowed
== AREAD
)
1457 if (access_allowed
== AWRITE
)
1463 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1464 flags
,flags2
,mode
));
1466 open_file(fnum
,cnum
,fname
,flags
|(flags2
&~(O_TRUNC
)),mode
);
1467 if (!Files
[fnum
].open
&& flags
==O_RDWR
&& errno
!=ENOENT
&& fcbopen
) {
1469 open_file(fnum
,cnum
,fname
,flags
,mode
);
1472 if (Files
[fnum
].open
) {
1486 Files
[fnum
].share_mode
= (deny_mode
<<4) | open_mode
;
1487 Files
[fnum
].share_pending
= True
;
1490 (*Access
) = open_mode
;
1494 if (file_existed
&& !(flags2
& O_TRUNC
)) *action
= 1;
1495 if (!file_existed
) *action
= 2;
1496 if (file_existed
&& (flags2
& O_TRUNC
)) *action
= 3;
1500 share_mode_pending
= True
;
1502 if ((flags2
&O_TRUNC
) && file_existed
)
1503 truncate_unless_locked(fnum
,cnum
);
1509 /*******************************************************************
1510 check for files that we should now set our share modes on
1511 ********************************************************************/
1512 static void check_share_modes(void)
1515 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
1516 if(Files
[i
].open
&& Files
[i
].share_pending
) {
1517 if (lp_share_modes(SNUM(Files
[i
].cnum
))) {
1519 get_share_mode_by_fnum(Files
[i
].cnum
,i
,&pid
);
1521 set_share_mode(i
,Files
[i
].share_mode
);
1522 Files
[i
].share_pending
= False
;
1525 Files
[i
].share_pending
= False
;
1531 /****************************************************************************
1532 seek a file. Try to avoid the seek if possible
1533 ****************************************************************************/
1534 int seek_file(int fnum
,int pos
)
1537 if (Files
[fnum
].print_file
&& POSTSCRIPT(Files
[fnum
].cnum
))
1540 Files
[fnum
].pos
= lseek(Files
[fnum
].fd
,pos
+offset
,SEEK_SET
) - offset
;
1541 return(Files
[fnum
].pos
);
1544 /****************************************************************************
1546 ****************************************************************************/
1547 int read_file(int fnum
,char *data
,int pos
,int mincnt
,int maxcnt
,int timeout
,BOOL exact
)
1551 if (!Files
[fnum
].can_write
)
1553 ret
= read_predict(Files
[fnum
].fd
,
1561 mincnt
= MAX(mincnt
-ret
,0);
1566 if (Files
[fnum
].mmap_ptr
)
1568 int num
= MIN(maxcnt
,Files
[fnum
].mmap_size
-pos
);
1571 memcpy(data
,Files
[fnum
].mmap_ptr
+pos
,num
);
1575 mincnt
= MAX(mincnt
-num
,0);
1584 if (seek_file(fnum
,pos
) != pos
)
1586 DEBUG(3,("Failed to seek to %d\n",pos
));
1591 ret
+= read_with_timeout(Files
[fnum
].fd
,
1602 /****************************************************************************
1604 ****************************************************************************/
1605 int write_file(int fnum
,char *data
,int n
)
1607 if (!Files
[fnum
].can_write
) {
1612 Files
[fnum
].modified
= True
;
1614 return(write_data(Files
[fnum
].fd
,data
,n
));
1618 static int old_umask
= 022;
1620 /****************************************************************************
1621 load parameters specific to a connection/service
1622 ****************************************************************************/
1623 BOOL
become_service(int cnum
,BOOL do_chdir
)
1625 extern char magic_char
;
1626 static int last_cnum
= -1;
1629 if (!OPEN_CNUM(cnum
))
1635 Connections
[cnum
].lastused
= smb_last_time
;
1640 ChDir(Connections
[cnum
].connectpath
) != 0 &&
1641 ChDir(Connections
[cnum
].origpath
) != 0)
1643 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1644 Connections
[cnum
].connectpath
,cnum
));
1648 if (cnum
== last_cnum
)
1653 case_default
= lp_defaultcase(snum
);
1654 case_preserve
= lp_preservecase(snum
);
1655 short_case_preserve
= lp_shortpreservecase(snum
);
1656 case_mangle
= lp_casemangle(snum
);
1657 case_sensitive
= lp_casesensitive(snum
);
1658 magic_char
= lp_magicchar(snum
);
1659 use_mangled_map
= (*lp_mangled_map(snum
) ? True
:False
);
1664 /****************************************************************************
1665 become the specified uid
1666 ****************************************************************************/
1667 static BOOL
become_uid(int uid
)
1669 if (initial_uid
!= 0)
1674 /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */
1677 priv
.pv_priv
[0] = 0;
1678 priv
.pv_priv
[1] = 0;
1679 if (setpriv(PRIV_SET
|PRIV_INHERITED
|PRIV_EFFECTIVE
|PRIV_BEQUEATH
,
1680 &priv
, sizeof(priv_t
)) < 0 ||
1681 setuidx(ID_REAL
|ID_EFFECTIVE
, (uid_t
)uid
) < 0 ||
1682 seteuid((uid_t
)uid
) < 0)
1683 DEBUG(1,("Can't set uid (AIX3)"));
1688 if (setresuid(-1,uid
,-1) != 0)
1690 if ((seteuid(uid
) != 0) &&
1694 DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n",
1695 uid
,getuid(), geteuid()));
1697 DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n"));
1701 if (((uid
== -1) || (uid
== 65535)) && geteuid() != uid
)
1703 DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n"));
1711 /****************************************************************************
1712 become the specified gid
1713 ****************************************************************************/
1714 static BOOL
become_gid(int gid
)
1716 if (initial_uid
!= 0)
1720 if (setresgid(-1,gid
,-1) != 0)
1722 if (setgid(gid
) != 0)
1725 DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n",
1726 gid
,getgid(),getegid()));
1728 DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n"));
1736 /****************************************************************************
1737 become the specified uid and gid
1738 ****************************************************************************/
1739 static BOOL
become_id(int uid
,int gid
)
1741 return(become_gid(gid
) && become_uid(uid
));
1744 /****************************************************************************
1745 become the guest user
1746 ****************************************************************************/
1747 static BOOL
become_guest(void)
1750 static struct passwd
*pass
=NULL
;
1752 if (initial_uid
!= 0)
1756 pass
= Get_Pwnam(lp_guestaccount(-1),True
);
1757 if (!pass
) return(False
);
1759 ret
= become_id(pass
->pw_uid
,pass
->pw_gid
);
1762 DEBUG(1,("Failed to become guest. Invalid guest account?\n"));
1764 last_user
.cnum
= -2;
1769 /*******************************************************************
1770 check if a username is OK
1771 ********************************************************************/
1772 static BOOL
check_user_ok(int cnum
,user_struct
*vuser
,int snum
)
1775 for (i
=0;i
<Connections
[cnum
].uid_cache
.entries
;i
++)
1776 if (Connections
[cnum
].uid_cache
.list
[i
] == vuser
->uid
) return(True
);
1778 if (!user_ok(vuser
->name
,snum
)) return(False
);
1780 i
= Connections
[cnum
].uid_cache
.entries
% UID_CACHE_SIZE
;
1781 Connections
[cnum
].uid_cache
.list
[i
] = vuser
->uid
;
1783 if (Connections
[cnum
].uid_cache
.entries
< UID_CACHE_SIZE
)
1784 Connections
[cnum
].uid_cache
.entries
++;
1790 /****************************************************************************
1791 become the user of a connection number
1792 ****************************************************************************/
1793 BOOL
become_user(int cnum
, int uid
)
1801 if (last_user
.cnum
== cnum
&& last_user
.uid
== uid
) {
1802 DEBUG(4,("Skipping become_user - already user\n"));
1808 if (!OPEN_CNUM(cnum
)) {
1809 DEBUG(2,("Connection %d not open\n",cnum
));
1813 snum
= Connections
[cnum
].service
;
1815 if (Connections
[cnum
].force_user
||
1816 lp_security() == SEC_SHARE
||
1817 !(vuser
= get_valid_user_struct(uid
)) ||
1818 !check_user_ok(cnum
,vuser
,snum
)) {
1819 uid
= Connections
[cnum
].uid
;
1820 gid
= Connections
[cnum
].gid
;
1821 groups
= Connections
[cnum
].groups
;
1822 ngroups
= Connections
[cnum
].ngroups
;
1825 DEBUG(2,("Invalid vuid used %d\n",uid
));
1829 if(!*lp_force_group(snum
))
1832 gid
= Connections
[cnum
].gid
;
1833 groups
= vuser
->user_groups
;
1834 ngroups
= vuser
->user_ngroups
;
1837 if (initial_uid
== 0)
1839 if (!become_gid(gid
)) return(False
);
1841 #ifndef NO_SETGROUPS
1842 if (!IS_IPC(cnum
)) {
1843 /* groups stuff added by ih/wreu */
1845 if (setgroups(ngroups
,groups
)<0)
1846 DEBUG(0,("setgroups call failed!\n"));
1850 if (!Connections
[cnum
].admin_user
&& !become_uid(uid
))
1854 new_umask
= 0777 & ~CREATE_MODE(cnum
);
1855 old_umask
= umask(new_umask
);
1857 last_user
.cnum
= cnum
;
1858 last_user
.uid
= uid
;
1860 DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d) new_umask=0%o\n",
1861 getuid(),geteuid(),getgid(),getegid(),new_umask
));
1866 /****************************************************************************
1867 unbecome the user of a connection number
1868 ****************************************************************************/
1869 BOOL
unbecome_user(void )
1871 if (last_user
.cnum
== -1)
1878 if (initial_uid
== 0)
1881 setresuid(-1,getuid(),-1);
1882 setresgid(-1,getgid(),-1);
1884 if (seteuid(initial_uid
) != 0)
1885 setuid(initial_uid
);
1886 setgid(initial_gid
);
1890 if (initial_uid
== 0)
1891 DEBUG(2,("Running with no EID\n"));
1892 initial_uid
= getuid();
1893 initial_gid
= getgid();
1895 if (geteuid() != initial_uid
)
1897 DEBUG(0,("Warning: You appear to have a trapdoor uid system\n"));
1898 initial_uid
= geteuid();
1900 if (getegid() != initial_gid
)
1902 DEBUG(0,("Warning: You appear to have a trapdoor gid system\n"));
1903 initial_gid
= getegid();
1907 if (ChDir(OriginalDir
) != 0)
1908 DEBUG(0,("%s chdir(%s) failed in unbecome_user\n",
1909 timestring(),OriginalDir
));
1911 DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
1912 getuid(),geteuid(),getgid(),getegid()));
1914 last_user
.cnum
= -1;
1919 /****************************************************************************
1920 find a service entry
1921 ****************************************************************************/
1922 int find_service(char *service
)
1926 string_sub(service
,"\\","/");
1928 iService
= lp_servicenumber(service
);
1930 /* now handle the special case of a home directory */
1933 char *phome_dir
= get_home_dir(service
);
1934 DEBUG(3,("checking for home directory %s gave %s\n",service
,
1935 phome_dir
?phome_dir
:"(NULL)"));
1939 if ((iHomeService
= lp_servicenumber(HOMES_NAME
)) >= 0)
1941 lp_add_home(service
,iHomeService
,phome_dir
);
1942 iService
= lp_servicenumber(service
);
1947 /* If we still don't have a service, attempt to add it as a printer. */
1950 int iPrinterService
;
1952 if ((iPrinterService
= lp_servicenumber(PRINTERS_NAME
)) >= 0)
1956 DEBUG(3,("checking whether %s is a valid printer name...\n", service
));
1958 if ((pszTemp
!= NULL
) && pcap_printername_ok(service
, pszTemp
))
1960 DEBUG(3,("%s is a valid printer name\n", service
));
1961 DEBUG(3,("adding %s as a printer service\n", service
));
1962 lp_add_printer(service
,iPrinterService
);
1963 iService
= lp_servicenumber(service
);
1965 DEBUG(0,("failed to add %s as a printer service!\n", service
));
1968 DEBUG(3,("%s is not a valid printer name\n", service
));
1972 /* just possibly it's a default service? */
1975 char *defservice
= lp_defaultservice();
1976 if (defservice
&& *defservice
&& !strequal(defservice
,service
)) {
1977 iService
= find_service(defservice
);
1978 if (iService
>= 0) {
1979 string_sub(service
,"_","/");
1980 iService
= lp_add_service(service
,iService
);
1986 if (!VALID_SNUM(iService
))
1988 DEBUG(0,("Invalid snum %d for %s\n",iService
,service
));
1993 DEBUG(3,("find_service() failed to find service %s\n", service
));
1999 /****************************************************************************
2000 create an error packet from a cached error.
2001 ****************************************************************************/
2002 int cached_error_packet(char *inbuf
,char *outbuf
,int fnum
,int line
)
2004 write_bmpx_struct
*wbmpx
= Files
[fnum
].wbmpx_ptr
;
2006 int32 eclass
= wbmpx
->wr_errclass
;
2007 int32 err
= wbmpx
->wr_error
;
2009 /* We can now delete the auxiliary struct */
2010 free((char *)wbmpx
);
2011 Files
[fnum
].wbmpx_ptr
= NULL
;
2012 return error_packet(inbuf
,outbuf
,eclass
,err
,line
);
2021 } unix_smb_errmap
[] =
2023 {EPERM
,ERRDOS
,ERRnoaccess
},
2024 {EACCES
,ERRDOS
,ERRnoaccess
},
2025 {ENOENT
,ERRDOS
,ERRbadfile
},
2026 {EIO
,ERRHRD
,ERRgeneral
},
2027 {EBADF
,ERRSRV
,ERRsrverror
},
2028 {EINVAL
,ERRSRV
,ERRsrverror
},
2029 {EEXIST
,ERRDOS
,ERRfilexists
},
2030 {ENFILE
,ERRDOS
,ERRnofids
},
2031 {EMFILE
,ERRDOS
,ERRnofids
},
2032 {ENOSPC
,ERRHRD
,ERRdiskfull
},
2034 {EDQUOT
,ERRHRD
,ERRdiskfull
},
2037 {ENOTEMPTY
,ERRDOS
,ERRnoaccess
},
2040 {EXDEV
,ERRDOS
,ERRdiffdevice
},
2042 {EROFS
,ERRHRD
,ERRnowrite
},
2047 /****************************************************************************
2048 create an error packet from errno
2049 ****************************************************************************/
2050 int unix_error_packet(char *inbuf
,char *outbuf
,int def_class
,uint32 def_code
,int line
)
2052 int eclass
=def_class
;
2056 if (unix_ERR_class
!= SUCCESS
)
2058 eclass
= unix_ERR_class
;
2059 ecode
= unix_ERR_code
;
2060 unix_ERR_class
= SUCCESS
;
2065 while (unix_smb_errmap
[i
].smbclass
!= 0)
2067 if (unix_smb_errmap
[i
].unixerror
== errno
)
2069 eclass
= unix_smb_errmap
[i
].smbclass
;
2070 ecode
= unix_smb_errmap
[i
].smbcode
;
2077 return(error_packet(inbuf
,outbuf
,eclass
,ecode
,line
));
2081 /****************************************************************************
2082 create an error packet. Normally called using the ERROR() macro
2083 ****************************************************************************/
2084 int error_packet(char *inbuf
,char *outbuf
,int error_class
,uint32 error_code
,int line
)
2086 int outsize
= set_message(outbuf
,0,0,True
);
2088 cmd
= CVAL(inbuf
,smb_com
);
2090 CVAL(outbuf
,smb_rcls
) = error_class
;
2091 SSVAL(outbuf
,smb_err
,error_code
);
2093 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
2096 (int)CVAL(inbuf
,smb_com
),
2097 smb_fn_name(CVAL(inbuf
,smb_com
)),
2102 DEBUG(3,("error string = %s\n",strerror(errno
)));
2108 #ifndef SIGCLD_IGNORE
2109 /****************************************************************************
2110 this prevents zombie child processes
2111 ****************************************************************************/
2112 static int sig_cld()
2114 static int depth
= 0;
2117 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2124 DEBUG(5,("got SIGCLD\n"));
2127 while (waitpid((pid_t
)-1,(int *)NULL
, WNOHANG
) > 0);
2131 /* Stevens, Adv. Unix Prog. says that on system V you must call
2132 wait before reinstalling the signal handler, because the kernel
2133 calls the handler from within the signal-call when there is a
2134 child that has exited. This would lead to an infinite recursion
2135 if done vice versa. */
2137 #ifndef DONT_REINSTALL_SIG
2138 #ifdef SIGCLD_IGNORE
2139 signal(SIGCLD
, SIG_IGN
);
2141 signal(SIGCLD
, SIGNAL_CAST sig_cld
);
2146 while (wait3(WAIT3_CAST1 NULL
, WNOHANG
, WAIT3_CAST2 NULL
) > 0);
2149 BlockSignals(False
);
2154 /****************************************************************************
2155 this is called when the client exits abruptly
2156 **************************************************************************/
2157 static int sig_pipe()
2159 exit_server("Got sigpipe\n");
2163 /****************************************************************************
2164 open the socket communication
2165 ****************************************************************************/
2166 static BOOL
open_sockets(BOOL is_daemon
,int port
)
2173 struct sockaddr addr
;
2174 int in_addrlen
= sizeof(addr
);
2177 #ifdef SIGCLD_IGNORE
2178 signal(SIGCLD
, SIG_IGN
);
2180 signal(SIGCLD
, SIGNAL_CAST sig_cld
);
2183 /* open an incoming socket */
2184 s
= open_socket_in(SOCK_STREAM
, port
, 0);
2188 /* ready to listen */
2189 if (listen(s
, 5) == -1)
2191 DEBUG(0,("listen: %s",strerror(errno
)));
2196 /* now accept incoming connections - forking a new process
2197 for each incoming connection */
2198 DEBUG(2,("waiting for a connection\n"));
2201 Client
= accept(s
,&addr
,&in_addrlen
);
2203 if (Client
== -1 && errno
== EINTR
)
2208 DEBUG(0,("accept: %s",strerror(errno
)));
2212 #ifdef NO_FORK_DEBUG
2213 #ifndef NO_SIGNAL_TEST
2214 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
2215 signal(SIGCLD
, SIGNAL_CAST SIG_DFL
);
2219 if (Client
!= -1 && fork()==0)
2221 #ifndef NO_SIGNAL_TEST
2222 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
2223 signal(SIGCLD
, SIGNAL_CAST SIG_DFL
);
2225 /* close our standard file descriptors */
2228 set_socket_options(Client
,"SO_KEEPALIVE");
2229 set_socket_options(Client
,user_socket_options
);
2233 close(Client
); /* The parent doesn't need this socket */
2239 /* We will abort gracefully when the client or remote system
2241 #ifndef NO_SIGNAL_TEST
2242 signal(SIGPIPE
, SIGNAL_CAST sig_pipe
);
2246 /* close our standard file descriptors */
2249 set_socket_options(Client
,"SO_KEEPALIVE");
2250 set_socket_options(Client
,user_socket_options
);
2257 /****************************************************************************
2258 check if a snum is in use
2259 ****************************************************************************/
2260 BOOL
snum_used(int snum
)
2263 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
2264 if (OPEN_CNUM(i
) && (SNUM(i
) == snum
))
2269 /****************************************************************************
2270 reload the services file
2271 **************************************************************************/
2272 BOOL
reload_services(BOOL test
)
2279 strcpy(fname
,lp_configfile());
2280 if (file_exist(fname
,NULL
) && !strcsequal(fname
,servicesf
))
2282 strcpy(servicesf
,fname
);
2289 if (test
&& !lp_file_list_changed())
2292 lp_killunused(snum_used
);
2294 ret
= lp_load(servicesf
,False
);
2296 /* perhaps the config filename is now set */
2298 reload_services(True
);
2305 set_socket_options(Client
,"SO_KEEPALIVE");
2306 set_socket_options(Client
,user_socket_options
);
2310 create_mangled_stack(lp_mangledstack());
2312 /* this forces service parameters to be flushed */
2313 become_service(-1,True
);
2320 /****************************************************************************
2321 this prevents zombie child processes
2322 ****************************************************************************/
2323 static int sig_hup()
2326 DEBUG(0,("Got SIGHUP\n"));
2327 reload_services(False
);
2328 #ifndef DONT_REINSTALL_SIG
2329 signal(SIGHUP
,SIGNAL_CAST sig_hup
);
2331 BlockSignals(False
);
2335 /****************************************************************************
2336 Setup the groups a user belongs to.
2337 ****************************************************************************/
2338 int setup_groups(char *user
, int uid
, int gid
, int *p_ngroups
,
2339 int **p_igroups
, gid_t
**p_groups
)
2341 if (-1 == initgroups(user
,gid
))
2345 DEBUG(0,("Unable to initgroups!\n"));
2346 if (gid
< 0 || gid
> 16000 || uid
< 0 || uid
> 16000)
2347 DEBUG(0,("This is probably a problem with the account %s\n",user
));
2355 ngroups
= getgroups(0,&grp
);
2358 igroups
= (int *)malloc(sizeof(int)*ngroups
);
2359 for (i
=0;i
<ngroups
;i
++)
2360 igroups
[i
] = 0x42424242;
2361 ngroups
= getgroups(ngroups
,(gid_t
*)igroups
);
2363 if (igroups
[0] == 0x42424242)
2366 *p_ngroups
= ngroups
;
2368 /* The following bit of code is very strange. It is due to the
2369 fact that some OSes use int* and some use gid_t* for
2370 getgroups, and some (like SunOS) use both, one in prototypes,
2371 and one in man pages and the actual code. Thus we detect it
2372 dynamically using some very ugly code */
2375 /* does getgroups return ints or gid_t ?? */
2376 static BOOL groups_use_ints
= True
;
2378 if (groups_use_ints
&&
2380 SVAL(igroups
,2) == 0x4242)
2381 groups_use_ints
= False
;
2383 for (i
=0;groups_use_ints
&& i
<ngroups
;i
++)
2384 if (igroups
[i
] == 0x42424242)
2385 groups_use_ints
= False
;
2387 if (groups_use_ints
)
2389 *p_igroups
= igroups
;
2390 *p_groups
= (gid_t
*)igroups
;
2394 gid_t
*groups
= (gid_t
*)igroups
;
2395 igroups
= (int *)malloc(sizeof(int)*ngroups
);
2396 for (i
=0;i
<ngroups
;i
++)
2397 igroups
[i
] = groups
[i
];
2398 *p_igroups
= igroups
;
2399 *p_groups
= (gid_t
*)groups
;
2402 DEBUG(3,("%s is in %d groups\n",user
,ngroups
));
2403 for (i
=0;i
<ngroups
;i
++)
2404 DEBUG(3,("%d ",igroups
[i
]));
2410 /****************************************************************************
2411 make a connection to a service
2412 ****************************************************************************/
2413 int make_connection(char *service
,char *user
,char *password
, int pwlen
, char *dev
,int vuid
)
2417 struct passwd
*pass
= NULL
;
2418 connection_struct
*pcon
;
2421 static BOOL first_connection
= True
;
2425 snum
= find_service(service
);
2428 if (strequal(service
,"IPC$"))
2430 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2434 DEBUG(0,("%s couldn't find service %s\n",timestring(),service
));
2438 if (strequal(service
,HOMES_NAME
))
2440 if (*user
&& Get_Pwnam(user
,True
))
2441 return(make_connection(user
,user
,password
,pwlen
,dev
,vuid
));
2443 if (validated_username(vuid
))
2445 strcpy(user
,validated_username(vuid
));
2446 return(make_connection(user
,user
,password
,pwlen
,dev
,vuid
));
2450 if (!lp_snum_ok(snum
) || !check_access(snum
)) {
2454 /* you can only connect to the IPC$ service as an ipc device */
2455 if (strequal(service
,"IPC$"))
2458 if (*dev
== '?' || !*dev
)
2460 if (lp_print_ok(snum
))
2461 strcpy(dev
,"LPT1:");
2466 /* if the request is as a printer and you can't print then refuse */
2468 if (!lp_print_ok(snum
) && (strncmp(dev
,"LPT",3) == 0)) {
2469 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2473 /* lowercase the user name */
2476 /* add it as a possible user name */
2477 add_session_user(service
);
2479 /* shall we let them in? */
2480 if (!authorise_login(snum
,user
,password
,pwlen
,&guest
,&force
,vuid
))
2482 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service
));
2486 cnum
= find_free_connection(str_checksum(service
) + str_checksum(user
));
2489 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2493 pcon
= &Connections
[cnum
];
2494 bzero((char *)pcon
,sizeof(*pcon
));
2496 /* find out some info about the user */
2497 pass
= Get_Pwnam(user
,True
);
2501 DEBUG(0,("%s couldn't find account %s\n",timestring(),user
));
2505 pcon
->read_only
= lp_readonly(snum
);
2509 StrnCpy(list
,lp_readlist(snum
),sizeof(pstring
)-1);
2510 string_sub(list
,"%S",service
);
2512 if (user_in_list(user
,list
))
2513 pcon
->read_only
= True
;
2515 StrnCpy(list
,lp_writelist(snum
),sizeof(pstring
)-1);
2516 string_sub(list
,"%S",service
);
2518 if (user_in_list(user
,list
))
2519 pcon
->read_only
= False
;
2522 /* admin user check */
2523 if (user_in_list(user
,lp_admin_users(snum
)) &&
2526 pcon
->admin_user
= True
;
2527 DEBUG(0,("%s logged in as admin user (root privileges)\n",user
));
2530 pcon
->admin_user
= False
;
2532 pcon
->force_user
= force
;
2533 pcon
->uid
= pass
->pw_uid
;
2534 pcon
->gid
= pass
->pw_gid
;
2535 pcon
->num_files_open
= 0;
2536 pcon
->lastused
= time(NULL
);
2537 pcon
->service
= snum
;
2539 pcon
->printer
= (strncmp(dev
,"LPT",3) == 0);
2540 pcon
->ipc
= (strncmp(dev
,"IPC",3) == 0);
2541 pcon
->dirptr
= NULL
;
2542 string_set(&pcon
->dirpath
,"");
2543 string_set(&pcon
->user
,user
);
2546 if (*lp_force_group(snum
))
2548 struct group
*gptr
= (struct group
*)getgrnam(lp_force_group(snum
));
2551 pcon
->gid
= gptr
->gr_gid
;
2552 DEBUG(3,("Forced group %s\n",lp_force_group(snum
)));
2555 DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum
)));
2559 if (*lp_force_user(snum
))
2561 struct passwd
*pass2
;
2563 strcpy(fuser
,lp_force_user(snum
));
2564 pass2
= (struct passwd
*)Get_Pwnam(fuser
,True
);
2567 pcon
->uid
= pass2
->pw_uid
;
2568 string_set(&pcon
->user
,fuser
);
2570 pcon
->force_user
= True
;
2571 DEBUG(3,("Forced user %s\n",fuser
));
2574 DEBUG(1,("Couldn't find user %s\n",fuser
));
2579 strcpy(s
,lp_pathname(snum
));
2580 standard_sub(cnum
,s
);
2581 string_set(&pcon
->connectpath
,s
);
2582 DEBUG(3,("Connect path is %s\n",s
));
2585 /* groups stuff added by ih */
2587 pcon
->groups
= NULL
;
2591 /* Find all the groups this uid is in and store them. Used by become_user() */
2592 setup_groups(pcon
->user
,pcon
->uid
,pcon
->gid
,&pcon
->ngroups
,&pcon
->igroups
,&pcon
->groups
);
2594 /* check number of connections */
2595 if (!claim_connection(cnum
,
2596 lp_servicename(SNUM(cnum
)),
2597 lp_max_connections(SNUM(cnum
)),False
))
2599 DEBUG(1,("too many connections - rejected\n"));
2603 if (lp_status(SNUM(cnum
)))
2604 claim_connection(cnum
,"STATUS.",MAXSTATUS
,first_connection
);
2606 first_connection
= False
;
2611 /* execute any "root preexec = " line */
2612 if (*lp_rootpreexec(SNUM(cnum
)))
2615 strcpy(cmd
,lp_rootpreexec(SNUM(cnum
)));
2616 standard_sub(cnum
,cmd
);
2617 DEBUG(5,("cmd=%s\n",cmd
));
2621 if (!become_user(cnum
,pcon
->uid
))
2623 DEBUG(0,("Can't become connected user!\n"));
2625 if (!IS_IPC(cnum
)) {
2626 yield_connection(cnum
,
2627 lp_servicename(SNUM(cnum
)),
2628 lp_max_connections(SNUM(cnum
)));
2629 if (lp_status(SNUM(cnum
))) yield_connection(cnum
,"STATUS.",MAXSTATUS
);
2634 if (ChDir(pcon
->connectpath
) != 0)
2636 DEBUG(0,("Can't change directory to %s\n",pcon
->connectpath
));
2639 if (!IS_IPC(cnum
)) {
2640 yield_connection(cnum
,
2641 lp_servicename(SNUM(cnum
)),
2642 lp_max_connections(SNUM(cnum
)));
2643 if (lp_status(SNUM(cnum
))) yield_connection(cnum
,"STATUS.",MAXSTATUS
);
2648 string_set(&pcon
->origpath
,pcon
->connectpath
);
2650 #if SOFTLINK_OPTIMISATION
2651 /* resolve any soft links early */
2654 strcpy(s
,pcon
->connectpath
);
2656 string_set(&pcon
->connectpath
,s
);
2657 ChDir(pcon
->connectpath
);
2661 num_connections_open
++;
2662 add_session_user(user
);
2664 /* execute any "preexec = " line */
2665 if (*lp_preexec(SNUM(cnum
)))
2668 strcpy(cmd
,lp_preexec(SNUM(cnum
)));
2669 standard_sub(cnum
,cmd
);
2673 /* we've finished with the sensitive stuff */
2677 extern struct from_host Client_info
;
2678 DEBUG(IS_IPC(cnum
)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2680 Client_info
.name
,Client_info
.addr
,
2681 lp_servicename(SNUM(cnum
)),user
,
2691 /****************************************************************************
2692 find first available file slot
2693 ****************************************************************************/
2694 int find_free_file(void )
2697 for (i
=1;i
<MAX_OPEN_FILES
;i
++)
2700 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2704 /****************************************************************************
2705 find first available connection slot, starting from a random position.
2706 The randomisation stops problems with the server dieing and clients
2707 thinking the server is still available.
2708 ****************************************************************************/
2709 static int find_free_connection(int hash
)
2713 hash
= (hash
% (MAX_CONNECTIONS
-2))+1;
2717 for (i
=hash
+1;i
!=hash
;)
2719 if (!Connections
[i
].open
&& Connections
[i
].used
== used
)
2721 DEBUG(3,("found free connection number %d\n",i
));
2725 if (i
== MAX_CONNECTIONS
)
2735 DEBUG(1,("ERROR! Out of connection structures\n"));
2740 /****************************************************************************
2741 reply for the core protocol
2742 ****************************************************************************/
2743 int reply_corep(char *outbuf
)
2745 int outsize
= set_message(outbuf
,1,0,True
);
2747 Protocol
= PROTOCOL_CORE
;
2753 /****************************************************************************
2754 reply for the coreplus protocol
2755 ****************************************************************************/
2756 int reply_coreplus(char *outbuf
)
2758 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2759 int outsize
= set_message(outbuf
,13,0,True
);
2760 SSVAL(outbuf
,smb_vwv5
,raw
); /* tell redirector we support
2761 readbraw and writebraw (possibly) */
2762 CVAL(outbuf
,smb_flg
) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2763 SSVAL(outbuf
,smb_vwv1
,0x1); /* user level security, don't encrypt */
2765 Protocol
= PROTOCOL_COREPLUS
;
2771 /****************************************************************************
2772 reply for the lanman 1.0 protocol
2773 ****************************************************************************/
2774 int reply_lanman1(char *outbuf
)
2776 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2778 BOOL doencrypt
= SMBENCRYPT();
2779 time_t t
= time(NULL
);
2781 if (lp_security()>=SEC_USER
) secword
|= 1;
2782 if (doencrypt
) secword
|= 2;
2784 set_message(outbuf
,13,doencrypt
?8:0,True
);
2785 SSVAL(outbuf
,smb_vwv1
,secword
);
2787 /* Create a token value and add it to the outgoing packet. */
2789 generate_next_challenge(smb_buf(outbuf
));
2792 Protocol
= PROTOCOL_LANMAN1
;
2794 if (lp_security() == SEC_SERVER
&& server_cryptkey(outbuf
)) {
2795 DEBUG(3,("using password server validation\n"));
2797 if (doencrypt
) set_challenge(smb_buf(outbuf
));
2801 CVAL(outbuf
,smb_flg
) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2802 SSVAL(outbuf
,smb_vwv2
,maxxmit
);
2803 SSVAL(outbuf
,smb_vwv3
,lp_maxmux()); /* maxmux */
2804 SSVAL(outbuf
,smb_vwv4
,1);
2805 SSVAL(outbuf
,smb_vwv5
,raw
); /* tell redirector we support
2806 readbraw writebraw (possibly) */
2807 SIVAL(outbuf
,smb_vwv6
,getpid());
2808 SSVAL(outbuf
,smb_vwv10
, TimeDiff(t
)/60);
2810 put_dos_date(outbuf
,smb_vwv8
,t
);
2812 return (smb_len(outbuf
)+4);
2816 /****************************************************************************
2817 reply for the lanman 2.0 protocol
2818 ****************************************************************************/
2819 int reply_lanman2(char *outbuf
)
2821 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2823 BOOL doencrypt
= SMBENCRYPT();
2824 time_t t
= time(NULL
);
2826 if (lp_security()>=SEC_USER
) secword
|= 1;
2827 if (doencrypt
) secword
|= 2;
2829 set_message(outbuf
,13,doencrypt
?8:0,True
);
2830 SSVAL(outbuf
,smb_vwv1
,secword
);
2832 /* Create a token value and add it to the outgoing packet. */
2834 generate_next_challenge(smb_buf(outbuf
));
2837 SIVAL(outbuf
,smb_vwv6
,getpid());
2839 Protocol
= PROTOCOL_LANMAN2
;
2841 if (lp_security() == SEC_SERVER
&& server_cryptkey(outbuf
)) {
2842 DEBUG(3,("using password server validation\n"));
2844 if (doencrypt
) set_challenge(smb_buf(outbuf
));
2848 CVAL(outbuf
,smb_flg
) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2849 SSVAL(outbuf
,smb_vwv2
,maxxmit
);
2850 SSVAL(outbuf
,smb_vwv3
,lp_maxmux());
2851 SSVAL(outbuf
,smb_vwv4
,1);
2852 SSVAL(outbuf
,smb_vwv5
,raw
); /* readbraw and/or writebraw */
2853 SSVAL(outbuf
,smb_vwv10
, TimeDiff(t
)/60);
2854 put_dos_date(outbuf
,smb_vwv8
,t
);
2856 return (smb_len(outbuf
)+4);
2859 /****************************************************************************
2860 reply for the nt protocol
2861 ****************************************************************************/
2862 int reply_nt1(char *outbuf
)
2864 int capabilities
=0x300; /* has dual names + lock_and_read */
2866 BOOL doencrypt
= SMBENCRYPT();
2868 if (lp_security()>=SEC_USER
) secword
|= 1;
2869 if (doencrypt
) secword
|= 2;
2871 set_message(outbuf
,17,doencrypt
?8:0,True
);
2872 CVAL(outbuf
,smb_vwv1
) = secword
;
2874 /* Create a token value and add it to the outgoing packet. */
2876 generate_next_challenge(smb_buf(outbuf
));
2877 /* Tell the nt machine how long the challenge is. */
2878 SSVALS(outbuf
,smb_vwv16
+1,8);
2882 SIVAL(outbuf
,smb_vwv7
+1,getpid()); /* session key */
2884 Protocol
= PROTOCOL_NT1
;
2886 if (lp_security() == SEC_SERVER
&& server_cryptkey(outbuf
)) {
2887 DEBUG(3,("using password server validation\n"));
2889 if (doencrypt
) set_challenge(smb_buf(outbuf
));
2893 if (lp_readraw() && lp_writeraw())
2896 SSVAL(outbuf
,smb_vwv1
+1,lp_maxmux()); /* maxmpx */
2897 SSVAL(outbuf
,smb_vwv2
+1,1); /* num vcs */
2898 SIVAL(outbuf
,smb_vwv3
+1,0xFFFF); /* max buffer */
2899 SIVAL(outbuf
,smb_vwv5
+1,0xFFFF); /* raw size */
2900 SIVAL(outbuf
,smb_vwv9
+1,capabilities
); /* capabilities */
2901 put_long_date(outbuf
+smb_vwv11
+1,time(NULL
));
2902 SSVALS(outbuf
,smb_vwv15
+1,TimeDiff(time(NULL
))/60);
2904 return (smb_len(outbuf
)+4);
2908 /* these are the protocol lists used for auto architecture detection:
2911 protocol [PC NETWORK PROGRAM 1.0]
2912 protocol [XENIX CORE]
2913 protocol [MICROSOFT NETWORKS 1.03]
2914 protocol [LANMAN1.0]
2915 protocol [Windows for Workgroups 3.1a]
2916 protocol [LM1.2X002]
2917 protocol [LANMAN2.1]
2918 protocol [NT LM 0.12]
2921 protocol [PC NETWORK PROGRAM 1.0]
2922 protocol [XENIX CORE]
2923 protocol [MICROSOFT NETWORKS 1.03]
2924 protocol [LANMAN1.0]
2925 protocol [Windows for Workgroups 3.1a]
2926 protocol [LM1.2X002]
2927 protocol [LANMAN2.1]
2928 protocol [NT LM 0.12]
2931 protocol [PC NETWORK PROGRAM 1.0]
2932 protocol [XENIX CORE]
2933 protocol [LANMAN1.0]
2934 protocol [LM1.2X002]
2935 protocol [LANMAN2.1]
2939 * Modified to recognize the architecture of the remote machine better.
2941 * This appears to be the matrix of which protocol is used by which
2943 Protocol WfWg Win95 WinNT OS/2
2944 PC NETWORK PROGRAM 1.0 1 1 1 1
2946 MICROSOFT NETWORKS 3.0 2 2
2948 MICROSOFT NETWORKS 1.03 3
2951 Windows for Workgroups 3.1a 5 5 5
2956 * tim@fsg.com 09/29/95
2959 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
2960 #define ARCH_WIN95 0x2
2961 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
2962 #define ARCH_WINNT 0x8
2963 #define ARCH_SAMBA 0x10
2965 #define ARCH_ALL 0x1F
2967 /* List of supported protocols, most desired first */
2971 int (*proto_reply_fn
)(char *);
2973 } supported_protocols
[] = {
2974 {"NT LANMAN 1.0", "NT1", reply_nt1
, PROTOCOL_NT1
},
2975 {"NT LM 0.12", "NT1", reply_nt1
, PROTOCOL_NT1
},
2976 {"LM1.2X002", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
2977 {"Samba", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
2978 {"DOS LM1.2X002", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
2979 {"LANMAN1.0", "LANMAN1", reply_lanman1
, PROTOCOL_LANMAN1
},
2980 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1
, PROTOCOL_LANMAN1
},
2981 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus
, PROTOCOL_COREPLUS
},
2982 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep
, PROTOCOL_CORE
},
2987 /****************************************************************************
2989 ****************************************************************************/
2990 static int reply_negprot(char *inbuf
,char *outbuf
)
2992 extern fstring remote_arch
;
2993 int outsize
= set_message(outbuf
,1,0,True
);
2998 int bcc
= SVAL(smb_buf(inbuf
),-2);
2999 int arch
= ARCH_ALL
;
3001 p
= smb_buf(inbuf
)+1;
3002 while (p
< (smb_buf(inbuf
) + bcc
))
3005 DEBUG(3,("Requested protocol [%s]\n",p
));
3006 if (strcsequal(p
,"Windows for Workgroups 3.1a"))
3007 arch
&= ( ARCH_WFWG
| ARCH_WIN95
| ARCH_WINNT
);
3008 else if (strcsequal(p
,"DOS LM1.2X002"))
3009 arch
&= ( ARCH_WFWG
| ARCH_WIN95
);
3010 else if (strcsequal(p
,"DOS LANMAN2.1"))
3011 arch
&= ( ARCH_WFWG
| ARCH_WIN95
);
3012 else if (strcsequal(p
,"NT LM 0.12"))
3013 arch
&= ( ARCH_WIN95
| ARCH_WINNT
);
3014 else if (strcsequal(p
,"LANMAN2.1"))
3015 arch
&= ( ARCH_WINNT
| ARCH_OS2
);
3016 else if (strcsequal(p
,"LM1.2X002"))
3017 arch
&= ( ARCH_WINNT
| ARCH_OS2
);
3018 else if (strcsequal(p
,"MICROSOFT NETWORKS 1.03"))
3020 else if (strcsequal(p
,"XENIX CORE"))
3021 arch
&= ( ARCH_WINNT
| ARCH_OS2
);
3022 else if (strcsequal(p
,"Samba")) {
3032 strcpy(remote_arch
,"Samba");
3035 strcpy(remote_arch
,"WfWg");
3038 strcpy(remote_arch
,"Win95");
3041 strcpy(remote_arch
,"WinNT");
3044 strcpy(remote_arch
,"OS2");
3047 strcpy(remote_arch
,"UNKNOWN");
3051 /* possibly reload - change of architecture */
3052 reload_services(True
);
3054 /* a special case to stop password server loops */
3055 if (Index
== 1 && strequal(remote_machine
,myhostname
) &&
3056 lp_security()==SEC_SERVER
)
3057 exit_server("Password server loop!");
3059 /* Check for protocols, most desirable first */
3060 for (protocol
= 0; supported_protocols
[protocol
].proto_name
; protocol
++)
3062 p
= smb_buf(inbuf
)+1;
3064 if (lp_maxprotocol() >= supported_protocols
[protocol
].protocol_level
)
3065 while (p
< (smb_buf(inbuf
) + bcc
))
3067 if (strequal(p
,supported_protocols
[protocol
].proto_name
))
3076 SSVAL(outbuf
,smb_vwv0
,choice
);
3078 extern fstring remote_proto
;
3079 strcpy(remote_proto
,supported_protocols
[protocol
].short_name
);
3080 reload_services(True
);
3081 outsize
= supported_protocols
[protocol
].proto_reply_fn(outbuf
);
3082 DEBUG(3,("Selected protocol %s\n",supported_protocols
[protocol
].proto_name
));
3085 DEBUG(0,("No protocol supported !\n"));
3087 SSVAL(outbuf
,smb_vwv0
,choice
);
3089 DEBUG(5,("%s negprot index=%d\n",timestring(),choice
));
3095 /****************************************************************************
3096 parse a connect packet
3097 ****************************************************************************/
3098 void parse_connect(char *buf
,char *service
,char *user
,char *password
,int *pwlen
,char *dev
)
3100 char *p
= smb_buf(buf
) + 1;
3103 DEBUG(4,("parsing connect string %s\n",p
));
3105 p2
= strrchr(p
,'\\');
3109 strcpy(service
,p2
+1);
3114 *pwlen
= strlen(password
);
3121 p
= strchr(service
,'%');
3130 /****************************************************************************
3131 close all open files for a connection
3132 ****************************************************************************/
3133 static void close_open_files(int cnum
)
3136 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
3137 if( Files
[i
].cnum
== cnum
&& Files
[i
].open
) {
3144 /****************************************************************************
3146 ****************************************************************************/
3147 void close_cnum(int cnum
, int uid
)
3149 extern struct from_host Client_info
;
3151 DirCacheFlush(SNUM(cnum
));
3155 if (!OPEN_CNUM(cnum
))
3157 DEBUG(0,("Can't close cnum %d\n",cnum
));
3161 DEBUG(IS_IPC(cnum
)?3:1,("%s %s (%s) closed connection to service %s\n",
3163 Client_info
.name
,Client_info
.addr
,
3164 lp_servicename(SNUM(cnum
))));
3166 yield_connection(cnum
,
3167 lp_servicename(SNUM(cnum
)),
3168 lp_max_connections(SNUM(cnum
)));
3170 if (lp_status(SNUM(cnum
)))
3171 yield_connection(cnum
,"STATUS.",MAXSTATUS
);
3173 close_open_files(cnum
);
3174 dptr_closecnum(cnum
);
3176 /* execute any "postexec = " line */
3177 if (*lp_postexec(SNUM(cnum
)) && become_user(cnum
,uid
))
3180 strcpy(cmd
,lp_postexec(SNUM(cnum
)));
3181 standard_sub(cnum
,cmd
);
3187 /* execute any "root postexec = " line */
3188 if (*lp_rootpostexec(SNUM(cnum
)))
3191 strcpy(cmd
,lp_rootpostexec(SNUM(cnum
)));
3192 standard_sub(cnum
,cmd
);
3196 Connections
[cnum
].open
= False
;
3197 num_connections_open
--;
3198 if (Connections
[cnum
].ngroups
&& Connections
[cnum
].groups
)
3200 if (Connections
[cnum
].igroups
!= (int *)Connections
[cnum
].groups
)
3201 free(Connections
[cnum
].groups
);
3202 free(Connections
[cnum
].igroups
);
3203 Connections
[cnum
].groups
= NULL
;
3204 Connections
[cnum
].igroups
= NULL
;
3205 Connections
[cnum
].ngroups
= 0;
3208 string_set(&Connections
[cnum
].user
,"");
3209 string_set(&Connections
[cnum
].dirpath
,"");
3210 string_set(&Connections
[cnum
].connectpath
,"");
3214 /****************************************************************************
3215 simple routines to do connection counting
3216 ****************************************************************************/
3217 BOOL
yield_connection(int cnum
,char *name
,int max_connections
)
3219 struct connect_record crec
;
3222 int mypid
= getpid();
3225 DEBUG(3,("Yielding connection to %d %s\n",cnum
,name
));
3227 if (max_connections
<= 0)
3230 bzero(&crec
,sizeof(crec
));
3232 strcpy(fname
,lp_lockdir());
3233 standard_sub(cnum
,fname
);
3234 trim_string(fname
,"","/");
3238 strcat(fname
,".LCK");
3240 f
= fopen(fname
,"r+");
3243 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname
,strerror(errno
)));
3247 fseek(f
,0,SEEK_SET
);
3249 /* find a free spot */
3250 for (i
=0;i
<max_connections
;i
++)
3252 if (fread(&crec
,sizeof(crec
),1,f
) != 1)
3254 DEBUG(2,("Entry not found in lock file %s\n",fname
));
3258 if (crec
.pid
== mypid
&& crec
.cnum
== cnum
)
3262 if (crec
.pid
!= mypid
|| crec
.cnum
!= cnum
)
3265 DEBUG(2,("Entry not found in lock file %s\n",fname
));
3269 bzero((void *)&crec
,sizeof(crec
));
3271 /* remove our mark */
3272 if (fseek(f
,i
*sizeof(crec
),SEEK_SET
) != 0 ||
3273 fwrite(&crec
,sizeof(crec
),1,f
) != 1)
3275 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname
,strerror(errno
)));
3280 DEBUG(3,("Yield successful\n"));
3287 /****************************************************************************
3288 simple routines to do connection counting
3289 ****************************************************************************/
3290 BOOL
claim_connection(int cnum
,char *name
,int max_connections
,BOOL Clear
)
3292 struct connect_record crec
;
3295 int snum
= SNUM(cnum
);
3299 if (max_connections
<= 0)
3302 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name
,max_connections
));
3304 strcpy(fname
,lp_lockdir());
3305 standard_sub(cnum
,fname
);
3306 trim_string(fname
,"","/");
3308 if (!directory_exist(fname
,NULL
))
3313 strcat(fname
,".LCK");
3315 if (!file_exist(fname
,NULL
))
3317 f
= fopen(fname
,"w");
3321 total_recs
= file_size(fname
) / sizeof(crec
);
3323 f
= fopen(fname
,"r+");
3327 DEBUG(1,("couldn't open lock file %s\n",fname
));
3331 /* find a free spot */
3332 for (i
=0;i
<max_connections
;i
++)
3335 if (i
>=total_recs
||
3336 fseek(f
,i
*sizeof(crec
),SEEK_SET
) != 0 ||
3337 fread(&crec
,sizeof(crec
),1,f
) != 1)
3339 if (foundi
< 0) foundi
= i
;
3343 if (Clear
&& crec
.pid
&& !process_exists(crec
.pid
))
3345 fseek(f
,i
*sizeof(crec
),SEEK_SET
);
3346 bzero((void *)&crec
,sizeof(crec
));
3347 fwrite(&crec
,sizeof(crec
),1,f
);
3348 if (foundi
< 0) foundi
= i
;
3351 if (foundi
< 0 && (!crec
.pid
|| !process_exists(crec
.pid
)))
3360 DEBUG(3,("no free locks in %s\n",fname
));
3365 /* fill in the crec */
3366 bzero((void *)&crec
,sizeof(crec
));
3367 crec
.magic
= 0x280267;
3368 crec
.pid
= getpid();
3370 crec
.uid
= Connections
[cnum
].uid
;
3371 crec
.gid
= Connections
[cnum
].gid
;
3372 StrnCpy(crec
.name
,lp_servicename(snum
),sizeof(crec
.name
)-1);
3373 crec
.start
= time(NULL
);
3376 extern struct from_host Client_info
;
3377 StrnCpy(crec
.machine
,Client_info
.name
,sizeof(crec
.machine
)-1);
3378 StrnCpy(crec
.addr
,Client_info
.addr
,sizeof(crec
.addr
)-1);
3382 if (fseek(f
,foundi
*sizeof(crec
),SEEK_SET
) != 0 ||
3383 fwrite(&crec
,sizeof(crec
),1,f
) != 1)
3394 /*******************************************************************
3395 prepare to dump a core file - carefully!
3396 ********************************************************************/
3397 static BOOL
dump_core(void)
3401 strcpy(dname
,debugf
);
3402 if ((p
=strrchr(dname
,'/'))) *p
=0;
3403 strcat(dname
,"/corefiles");
3405 sys_chown(dname
,getuid(),getgid());
3407 if (chdir(dname
)) return(False
);
3410 #ifndef NO_GETRLIMIT
3414 getrlimit(RLIMIT_CORE
, &rlp
);
3415 rlp
.rlim_cur
= MAX(4*1024*1024,rlp
.rlim_cur
);
3416 setrlimit(RLIMIT_CORE
, &rlp
);
3417 getrlimit(RLIMIT_CORE
, &rlp
);
3418 DEBUG(3,("Core limits now %d %d\n",rlp
.rlim_cur
,rlp
.rlim_max
));
3424 DEBUG(0,("Dumping core in %s\n",dname
));
3429 /****************************************************************************
3431 ****************************************************************************/
3432 void exit_server(char *reason
)
3434 static int firsttime
=1;
3437 if (!firsttime
) exit(0);
3441 DEBUG(2,("Closing connections\n"));
3442 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
3443 if (Connections
[i
].open
)
3446 if (dcelogin_atmost_once
)
3450 int oldlevel
= DEBUGLEVEL
;
3452 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message
)));
3454 show_msg(last_inbuf
);
3455 DEBUGLEVEL
= oldlevel
;
3456 DEBUG(0,("===============================================================\n"));
3458 if (dump_core()) return;
3461 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason
?reason
:""));
3465 /****************************************************************************
3466 do some standard substitutions in a string
3467 ****************************************************************************/
3468 void standard_sub(int cnum
,char *s
)
3470 if (!strchr(s
,'%')) return;
3472 if (VALID_CNUM(cnum
))
3474 string_sub(s
,"%S",lp_servicename(Connections
[cnum
].service
));
3475 string_sub(s
,"%P",Connections
[cnum
].connectpath
);
3476 string_sub(s
,"%u",Connections
[cnum
].user
);
3477 if (strstr(s
,"%H")) {
3478 char *home
= get_home_dir(Connections
[cnum
].user
);
3479 if (home
) string_sub(s
,"%H",home
);
3481 string_sub(s
,"%g",gidtoname(Connections
[cnum
].gid
));
3483 standard_sub_basic(s
);
3487 These flags determine some of the permissions required to do an operation
3489 Note that I don't set NEED_WRITE on some write operations because they
3490 are used by some brain-dead clients when printing, and I don't want to
3491 force write permissions on print services.
3493 #define AS_USER (1<<0)
3494 #define NEED_WRITE (1<<1)
3495 #define TIME_INIT (1<<2)
3496 #define CAN_IPC (1<<3)
3497 #define AS_GUEST (1<<5)
3501 define a list of possible SMB messages and their corresponding
3502 functions. Any message that has a NULL function is unimplemented -
3503 please feel free to contribute implementations!
3505 struct smb_message_struct
3519 {SMBnegprot
,"SMBnegprot",reply_negprot
,0},
3520 {SMBtcon
,"SMBtcon",reply_tcon
,0},
3521 {SMBtdis
,"SMBtdis",reply_tdis
,0},
3522 {SMBexit
,"SMBexit",reply_exit
,0},
3523 {SMBioctl
,"SMBioctl",reply_ioctl
,0},
3524 {SMBecho
,"SMBecho",reply_echo
,0},
3525 {SMBsesssetupX
,"SMBsesssetupX",reply_sesssetup_and_X
,0},
3526 {SMBtconX
,"SMBtconX",reply_tcon_and_X
,0},
3527 {SMBulogoffX
, "SMBulogoffX", reply_ulogoffX
, 0},
3528 {SMBgetatr
,"SMBgetatr",reply_getatr
,AS_USER
},
3529 {SMBsetatr
,"SMBsetatr",reply_setatr
,AS_USER
| NEED_WRITE
},
3530 {SMBchkpth
,"SMBchkpth",reply_chkpth
,AS_USER
},
3531 {SMBsearch
,"SMBsearch",reply_search
,AS_USER
},
3532 {SMBopen
,"SMBopen",reply_open
,AS_USER
},
3534 /* note that SMBmknew and SMBcreate are deliberately overloaded */
3535 {SMBcreate
,"SMBcreate",reply_mknew
,AS_USER
},
3536 {SMBmknew
,"SMBmknew",reply_mknew
,AS_USER
},
3538 {SMBunlink
,"SMBunlink",reply_unlink
,AS_USER
| NEED_WRITE
},
3539 {SMBread
,"SMBread",reply_read
,AS_USER
},
3540 {SMBwrite
,"SMBwrite",reply_write
,AS_USER
},
3541 {SMBclose
,"SMBclose",reply_close
,AS_USER
},
3542 {SMBmkdir
,"SMBmkdir",reply_mkdir
,AS_USER
| NEED_WRITE
},
3543 {SMBrmdir
,"SMBrmdir",reply_rmdir
,AS_USER
| NEED_WRITE
},
3544 {SMBdskattr
,"SMBdskattr",reply_dskattr
,AS_USER
},
3545 {SMBmv
,"SMBmv",reply_mv
,AS_USER
| NEED_WRITE
},
3547 /* this is a Pathworks specific call, allowing the
3548 changing of the root path */
3549 {pSETDIR
,"pSETDIR",reply_setdir
,AS_USER
},
3551 {SMBlseek
,"SMBlseek",reply_lseek
,AS_USER
},
3552 {SMBflush
,"SMBflush",reply_flush
,AS_USER
},
3553 {SMBctemp
,"SMBctemp",reply_ctemp
,AS_USER
},
3554 {SMBsplopen
,"SMBsplopen",reply_printopen
,AS_USER
},
3555 {SMBsplclose
,"SMBsplclose",reply_printclose
,AS_USER
},
3556 {SMBsplretq
,"SMBsplretq",reply_printqueue
,AS_USER
},
3557 {SMBsplwr
,"SMBsplwr",reply_printwrite
,AS_USER
},
3558 {SMBlock
,"SMBlock",reply_lock
,AS_USER
},
3559 {SMBunlock
,"SMBunlock",reply_unlock
,AS_USER
},
3561 /* CORE+ PROTOCOL FOLLOWS */
3563 {SMBreadbraw
,"SMBreadbraw",reply_readbraw
,AS_USER
},
3564 {SMBwritebraw
,"SMBwritebraw",reply_writebraw
,AS_USER
},
3565 {SMBwriteclose
,"SMBwriteclose",reply_writeclose
,AS_USER
},
3566 {SMBlockread
,"SMBlockread",reply_lockread
,AS_USER
},
3567 {SMBwriteunlock
,"SMBwriteunlock",reply_writeunlock
,AS_USER
},
3569 /* LANMAN1.0 PROTOCOL FOLLOWS */
3571 {SMBreadBmpx
,"SMBreadBmpx",reply_readbmpx
,AS_USER
},
3572 {SMBreadBs
,"SMBreadBs",NULL
,AS_USER
},
3573 {SMBwriteBmpx
,"SMBwriteBmpx",reply_writebmpx
,AS_USER
},
3574 {SMBwriteBs
,"SMBwriteBs",reply_writebs
,AS_USER
},
3575 {SMBwritec
,"SMBwritec",NULL
,AS_USER
},
3576 {SMBsetattrE
,"SMBsetattrE",reply_setattrE
,AS_USER
| NEED_WRITE
},
3577 {SMBgetattrE
,"SMBgetattrE",reply_getattrE
,AS_USER
},
3578 {SMBtrans
,"SMBtrans",reply_trans
,AS_USER
| CAN_IPC
},
3579 {SMBtranss
,"SMBtranss",NULL
,AS_USER
| CAN_IPC
},
3580 {SMBioctls
,"SMBioctls",NULL
,AS_USER
},
3581 {SMBcopy
,"SMBcopy",reply_copy
,AS_USER
| NEED_WRITE
},
3582 {SMBmove
,"SMBmove",NULL
,AS_USER
| NEED_WRITE
},
3584 {SMBopenX
,"SMBopenX",reply_open_and_X
,AS_USER
},
3585 {SMBreadX
,"SMBreadX",reply_read_and_X
,AS_USER
},
3586 {SMBwriteX
,"SMBwriteX",reply_write_and_X
,AS_USER
},
3587 {SMBlockingX
,"SMBlockingX",reply_lockingX
,AS_USER
},
3589 {SMBffirst
,"SMBffirst",reply_search
,AS_USER
},
3590 {SMBfunique
,"SMBfunique",reply_search
,AS_USER
},
3591 {SMBfclose
,"SMBfclose",reply_fclose
,AS_USER
},
3593 /* LANMAN2.0 PROTOCOL FOLLOWS */
3594 {SMBfindnclose
, "SMBfindnclose", reply_findnclose
, AS_USER
},
3595 {SMBfindclose
, "SMBfindclose", reply_findclose
,AS_USER
},
3596 {SMBtrans2
, "SMBtrans2", reply_trans2
, AS_USER
},
3597 {SMBtranss2
, "SMBtranss2", reply_transs2
, AS_USER
},
3599 /* messaging routines */
3600 {SMBsends
,"SMBsends",reply_sends
,AS_GUEST
},
3601 {SMBsendstrt
,"SMBsendstrt",reply_sendstrt
,AS_GUEST
},
3602 {SMBsendend
,"SMBsendend",reply_sendend
,AS_GUEST
},
3603 {SMBsendtxt
,"SMBsendtxt",reply_sendtxt
,AS_GUEST
},
3605 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3607 {SMBsendb
,"SMBsendb",NULL
,AS_GUEST
},
3608 {SMBfwdname
,"SMBfwdname",NULL
,AS_GUEST
},
3609 {SMBcancelf
,"SMBcancelf",NULL
,AS_GUEST
},
3610 {SMBgetmac
,"SMBgetmac",NULL
,AS_GUEST
}
3613 /****************************************************************************
3614 return a string containing the function name of a SMB command
3615 ****************************************************************************/
3616 char *smb_fn_name(int type
)
3618 static char *unknown_name
= "SMBunknown";
3619 static int num_smb_messages
=
3620 sizeof(smb_messages
) / sizeof(struct smb_message_struct
);
3623 for (match
=0;match
<num_smb_messages
;match
++)
3624 if (smb_messages
[match
].code
== type
)
3627 if (match
== num_smb_messages
)
3628 return(unknown_name
);
3630 return(smb_messages
[match
].name
);
3634 /****************************************************************************
3635 do a switch on the message type, and return the response size
3636 ****************************************************************************/
3637 static int switch_message(int type
,char *inbuf
,char *outbuf
,int size
,int bufsize
)
3641 static int num_smb_messages
=
3642 sizeof(smb_messages
) / sizeof(struct smb_message_struct
);
3646 struct timeval msg_start_time
;
3647 struct timeval msg_end_time
;
3648 static unsigned long total_time
= 0;
3650 GetTimeOfDay(&msg_start_time
);
3657 last_message
= type
;
3659 /* make sure this is an SMB packet */
3660 if (strncmp(smb_base(inbuf
),"\377SMB",4) != 0)
3662 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf
)));
3666 for (match
=0;match
<num_smb_messages
;match
++)
3667 if (smb_messages
[match
].code
== type
)
3670 if (match
== num_smb_messages
)
3672 DEBUG(0,("Unknown message type %d!\n",type
));
3673 outsize
= reply_unknown(inbuf
,outbuf
);
3677 DEBUG(3,("switch message %s (pid %d)\n",smb_messages
[match
].name
,pid
));
3678 if (smb_messages
[match
].fn
)
3680 int cnum
= SVAL(inbuf
,smb_tid
);
3681 int flags
= smb_messages
[match
].flags
;
3682 int uid
= SVAL(inbuf
,smb_uid
);
3684 /* does this protocol need to be run as root? */
3685 if (!(flags
& AS_USER
))
3688 /* does this protocol need to be run as the connected user? */
3689 if ((flags
& AS_USER
) && !become_user(cnum
,uid
))
3690 return(ERROR(ERRSRV
,ERRinvnid
));
3692 /* does it need write permission? */
3693 if ((flags
& NEED_WRITE
) && !CAN_WRITE(cnum
))
3694 return(ERROR(ERRSRV
,ERRaccess
));
3696 /* ipc services are limited */
3697 if (IS_IPC(cnum
) && (flags
& AS_USER
) && !(flags
& CAN_IPC
))
3698 return(ERROR(ERRSRV
,ERRaccess
));
3700 /* load service specific parameters */
3701 if (OPEN_CNUM(cnum
) && !become_service(cnum
,(flags
& AS_USER
)?True
:False
))
3702 return(ERROR(ERRSRV
,ERRaccess
));
3704 /* does this protocol need to be run as guest? */
3705 if ((flags
& AS_GUEST
) && (!become_guest() || !check_access(-1)))
3706 return(ERROR(ERRSRV
,ERRaccess
));
3710 outsize
= smb_messages
[match
].fn(inbuf
,outbuf
,size
,bufsize
);
3714 outsize
= reply_unknown(inbuf
,outbuf
);
3719 GetTimeOfDay(&msg_end_time
);
3720 if (!(smb_messages
[match
].flags
& TIME_INIT
))
3722 smb_messages
[match
].time
= 0;
3723 smb_messages
[match
].flags
|= TIME_INIT
;
3726 unsigned long this_time
=
3727 (msg_end_time
.tv_sec
- msg_start_time
.tv_sec
)*1e6
+
3728 (msg_end_time
.tv_usec
- msg_start_time
.tv_usec
);
3729 smb_messages
[match
].time
+= this_time
;
3730 total_time
+= this_time
;
3732 DEBUG(2,("TIME %s %d usecs %g pct\n",
3733 smb_fn_name(type
),smb_messages
[match
].time
,
3734 (100.0*smb_messages
[match
].time
) / total_time
));
3741 /****************************************************************************
3742 construct a chained reply and add it to the already made reply
3744 inbuf points to the original message start.
3745 inbuf2 points to the smb_wct part of the secondary message
3746 type is the type of the secondary message
3747 outbuf points to the original outbuffer
3748 outbuf2 points to the smb_wct field of the new outbuffer
3749 size is the total length of the incoming message (from inbuf1)
3750 bufsize is the total buffer size
3752 return how many bytes were added to the response
3753 ****************************************************************************/
3754 int chain_reply(int type
,char *inbuf
,char *inbuf2
,char *outbuf
,char *outbuf2
,int size
,int bufsize
)
3758 static BOOL in_chain
= False
;
3759 static char *last_outbuf
=NULL
;
3760 BOOL was_inchain
= in_chain
;
3761 int insize_remaining
;
3762 static int insize_deleted
;
3765 chain_size
+= PTR_DIFF(outbuf2
,outbuf
) - smb_wct
;
3767 outbuf
= last_outbuf
;
3773 inbuf2
-= insize_deleted
;
3774 insize_remaining
= size
- PTR_DIFF(inbuf2
,inbuf
);
3775 insize_deleted
+= size
- (insize_remaining
+ smb_wct
);
3778 last_outbuf
= outbuf
;
3781 /* allocate some space for the in and out buffers of the chained message */
3782 ibuf
= (char *)malloc(size
+ SAFETY_MARGIN
);
3783 obuf
= (char *)malloc(bufsize
+ SAFETY_MARGIN
);
3787 DEBUG(0,("Out of memory in chain reply\n"));
3788 return(ERROR(ERRSRV
,ERRnoresource
));
3791 ibuf
+= SMB_ALIGNMENT
;
3792 obuf
+= SMB_ALIGNMENT
;
3794 /* create the in buffer */
3795 memcpy(ibuf
,inbuf
,smb_wct
);
3796 memcpy(ibuf
+smb_wct
,inbuf2
,insize_remaining
);
3797 CVAL(ibuf
,smb_com
) = type
;
3799 /* create the out buffer */
3800 bzero(obuf
,smb_size
);
3802 set_message(obuf
,0,0,True
);
3803 CVAL(obuf
,smb_com
) = CVAL(ibuf
,smb_com
);
3805 memcpy(obuf
+4,ibuf
+4,4);
3806 CVAL(obuf
,smb_rcls
) = SUCCESS
;
3807 CVAL(obuf
,smb_reh
) = 0;
3808 CVAL(obuf
,smb_flg
) = 0x80 | (CVAL(ibuf
,smb_flg
) & 0x8); /* bit 7 set
3810 SSVAL(obuf
,smb_flg2
,1); /* say we support long filenames */
3811 SSVAL(obuf
,smb_err
,SUCCESS
);
3812 SSVAL(obuf
,smb_tid
,SVAL(inbuf
,smb_tid
));
3813 SSVAL(obuf
,smb_pid
,SVAL(inbuf
,smb_pid
));
3814 SSVAL(obuf
,smb_uid
,SVAL(inbuf
,smb_uid
));
3815 SSVAL(obuf
,smb_mid
,SVAL(inbuf
,smb_mid
));
3817 DEBUG(3,("Chained message\n"));
3820 /* process the request */
3821 outsize
= switch_message(type
,ibuf
,obuf
,smb_wct
+insize_remaining
,
3822 bufsize
-chain_size
);
3824 /* copy the new reply header over the old one, but preserve
3825 the smb_com field */
3826 memcpy(outbuf
+smb_com
+1,obuf
+smb_com
+1,smb_wct
-(smb_com
+1));
3828 /* and copy the data from the reply to the right spot */
3829 memcpy(outbuf2
,obuf
+smb_wct
,outsize
- smb_wct
);
3831 /* free the allocated buffers */
3832 if (ibuf
) free(ibuf
-SMB_ALIGNMENT
);
3833 if (obuf
) free(obuf
-SMB_ALIGNMENT
);
3835 in_chain
= was_inchain
;
3837 /* return how much extra has been added to the packet */
3838 return(outsize
- smb_wct
);
3843 /****************************************************************************
3844 construct a reply to the incoming packet
3845 ****************************************************************************/
3846 int construct_reply(char *inbuf
,char *outbuf
,int size
,int bufsize
)
3848 int type
= CVAL(inbuf
,smb_com
);
3850 int msg_type
= CVAL(inbuf
,0);
3852 smb_last_time
= time(NULL
);
3856 bzero(outbuf
,smb_size
);
3859 return(reply_special(inbuf
,outbuf
));
3861 CVAL(outbuf
,smb_com
) = CVAL(inbuf
,smb_com
);
3862 set_message(outbuf
,0,0,True
);
3864 memcpy(outbuf
+4,inbuf
+4,4);
3865 CVAL(outbuf
,smb_rcls
) = SUCCESS
;
3866 CVAL(outbuf
,smb_reh
) = 0;
3867 CVAL(outbuf
,smb_flg
) = 0x80 | (CVAL(inbuf
,smb_flg
) & 0x8); /* bit 7 set
3869 SSVAL(outbuf
,smb_flg2
,1); /* say we support long filenames */
3870 SSVAL(outbuf
,smb_err
,SUCCESS
);
3871 SSVAL(outbuf
,smb_tid
,SVAL(inbuf
,smb_tid
));
3872 SSVAL(outbuf
,smb_pid
,SVAL(inbuf
,smb_pid
));
3873 SSVAL(outbuf
,smb_uid
,SVAL(inbuf
,smb_uid
));
3874 SSVAL(outbuf
,smb_mid
,SVAL(inbuf
,smb_mid
));
3876 outsize
= switch_message(type
,inbuf
,outbuf
,size
,bufsize
);
3879 smb_setlen(outbuf
,outsize
- 4);
3884 /****************************************************************************
3885 process commands from the client
3886 ****************************************************************************/
3889 static int trans_num
= 0;
3891 extern struct from_host Client_info
;
3894 fromhost(Client
,&Client_info
);
3896 InBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3897 OutBuffer
= (char *)malloc(BUFFER_SIZE
+ SAFETY_MARGIN
);
3898 if ((InBuffer
== NULL
) || (OutBuffer
== NULL
))
3901 InBuffer
+= SMB_ALIGNMENT
;
3902 OutBuffer
+= SMB_ALIGNMENT
;
3905 DEBUG(3,("priming nmbd\n"));
3908 ip
= *interpret_addr2("localhost");
3909 if (zero_ip(ip
)) ip
= *interpret_addr2("127.0.0.1");
3911 send_one_packet(OutBuffer
,1,ip
,137,SOCK_DGRAM
);
3915 last_user
.cnum
= -1;
3923 int deadtime
= lp_deadtime()*60;
3925 int last_keepalive
=0;
3928 deadtime
= DEFAULT_SMBD_TIMEOUT
;
3930 if (lp_readprediction())
3931 do_read_prediction();
3934 extern pstring share_del_pending
;
3935 if (*share_del_pending
) {
3937 if (!unlink(share_del_pending
))
3938 DEBUG(3,("Share file deleted %s\n",share_del_pending
));
3940 DEBUG(2,("Share del failed of %s\n",share_del_pending
));
3941 share_del_pending
[0] = 0;
3945 if (share_mode_pending
) {
3947 check_share_modes();
3948 share_mode_pending
=False
;
3953 for (counter
=SMBD_SELECT_LOOP
;
3954 !receive_smb(Client
,InBuffer
,SMBD_SELECT_LOOP
*1000);
3955 counter
+= SMBD_SELECT_LOOP
)
3959 BOOL allidle
= True
;
3960 extern int keepalive
;
3962 /* check for socket failure */
3963 if (errno
== EBADF
) {
3964 DEBUG(3,("%s Bad file descriptor - exiting\n",timestring()));
3970 /* become root again if waiting */
3973 /* check for smb.conf reload */
3974 if (!(counter
%SMBD_RELOAD_CHECK
))
3975 reload_services(True
);
3977 /* check the share modes every 10 secs */
3978 if (!(counter
%SHARE_MODES_CHECK
))
3979 check_share_modes();
3981 /* clean the share modes every 5 minutes */
3982 if (!(counter
%SHARE_MODES_CLEAN
))
3983 clean_share_files();
3985 /* automatic timeout if all connections are closed */
3986 if (num_connections_open
==0 && counter
>= IDLE_CLOSED_TIMEOUT
) {
3987 DEBUG(2,("%s Closing idle connection\n",timestring()));
3991 if (keepalive
&& (counter
-last_keepalive
)>keepalive
) {
3992 if (!send_keepalive(Client
)) {
3993 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3996 last_keepalive
= counter
;
3999 /* check for connection timeouts */
4000 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
4001 if (Connections
[i
].open
)
4003 /* close dirptrs on connections that are idle */
4004 if ((t
-Connections
[i
].lastused
)>DPTR_IDLE_TIMEOUT
)
4007 if (Connections
[i
].num_files_open
> 0 ||
4008 (t
-Connections
[i
].lastused
)<deadtime
)
4012 if (allidle
&& num_connections_open
>0) {
4013 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
4018 msg_type
= CVAL(InBuffer
,0);
4019 msg_flags
= CVAL(InBuffer
,1);
4020 type
= CVAL(InBuffer
,smb_com
);
4022 len
= smb_len(InBuffer
);
4024 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type
,len
));
4028 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num
,nread
));
4031 if(trans_num
== 1 && VT_Check(InBuffer
)) {
4041 nread
= construct_reply(InBuffer
,OutBuffer
,nread
,maxxmit
);
4044 if (CVAL(OutBuffer
,0) == 0)
4045 show_msg(OutBuffer
);
4047 if (nread
!= smb_len(OutBuffer
) + 4)
4049 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
4051 smb_len(OutBuffer
)));
4054 send_smb(Client
,OutBuffer
);
4061 /****************************************************************************
4062 initialise connect, service and file structs
4063 ****************************************************************************/
4064 static void init_structs(void )
4067 get_myname(myhostname
,&myip
);
4069 for (i
=0;i
<MAX_CONNECTIONS
;i
++)
4071 Connections
[i
].open
= False
;
4072 Connections
[i
].num_files_open
=0;
4073 Connections
[i
].lastused
=0;
4074 Connections
[i
].used
=False
;
4075 string_init(&Connections
[i
].user
,"");
4076 string_init(&Connections
[i
].dirpath
,"");
4077 string_init(&Connections
[i
].connectpath
,"");
4078 string_init(&Connections
[i
].origpath
,"");
4081 for (i
=0;i
<MAX_OPEN_FILES
;i
++)
4083 Files
[i
].open
= False
;
4084 string_init(&Files
[i
].name
,"");
4090 /****************************************************************************
4091 usage on the program
4092 ****************************************************************************/
4093 void usage(char *pname
)
4095 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4097 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname
);
4098 printf("Version %s\n",VERSION
);
4099 printf("\t-D become a daemon\n");
4100 printf("\t-p port listen on the specified port\n");
4101 printf("\t-d debuglevel set the debuglevel\n");
4102 printf("\t-l log basename. Basename for log/debug files\n");
4103 printf("\t-s services file. Filename of services file\n");
4104 printf("\t-P passive only\n");
4105 printf("\t-a overwrite log file, don't append\n");
4110 /****************************************************************************
4112 ****************************************************************************/
4113 int main(int argc
,char *argv
[])
4115 extern BOOL append_log
;
4116 /* shall I run as a daemon */
4117 BOOL is_daemon
= False
;
4120 extern char *optarg
;
4122 #ifdef NEED_AUTH_PARAMETERS
4123 set_auth_parameters(argc
,argv
);
4134 strcpy(debugf
,SMBLOGFILE
);
4136 setup_logging(argv
[0],False
);
4138 charset_initialise();
4140 /* make absolutely sure we run as root - to handle cases whre people
4141 are crazy enough to have it setuid */
4151 fault_setup(exit_server
);
4153 umask(0777 & ~DEF_CREATE_MASK
);
4155 initial_uid
= geteuid();
4156 initial_gid
= getegid();
4158 if (initial_gid
!= 0 && initial_uid
== 0)
4168 initial_uid
= geteuid();
4169 initial_gid
= getegid();
4172 /* this is for people who can't start the program correctly */
4173 while (argc
> 1 && (*argv
[1] != '-'))
4179 while ((opt
= getopt(argc
, argv
, "O:i:l:s:d:Dp:hPa")) != EOF
)
4183 strcpy(user_socket_options
,optarg
);
4186 strcpy(scope
,optarg
);
4190 extern BOOL passive
;
4195 strcpy(servicesf
,optarg
);
4198 strcpy(debugf
,optarg
);
4202 extern BOOL append_log
;
4203 append_log
= !append_log
;
4213 DEBUGLEVEL
= atoi(optarg
);
4216 port
= atoi(optarg
);
4229 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION
));
4230 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4234 #ifndef NO_GETRLIMIT
4235 #ifdef RLIMIT_NOFILE
4238 getrlimit(RLIMIT_NOFILE
, &rlp
);
4239 rlp
.rlim_cur
= (MAX_OPEN_FILES
>rlp
.rlim_max
)? rlp
.rlim_max
:MAX_OPEN_FILES
;
4240 setrlimit(RLIMIT_NOFILE
, &rlp
);
4241 getrlimit(RLIMIT_NOFILE
, &rlp
);
4242 DEBUG(3,("Maximum number of open files per session is %d\n",rlp
.rlim_cur
));
4248 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4249 getuid(),getgid(),geteuid(),getegid()));
4251 if (sizeof(uint16
) < 2 || sizeof(uint32
) < 4)
4253 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4259 if (!reload_services(False
))
4262 #ifndef NO_SIGNAL_TEST
4263 signal(SIGHUP
,SIGNAL_CAST sig_hup
);
4266 DEBUG(3,("%s loaded services\n",timestring()));
4268 if (!is_daemon
&& !is_a_socket(0))
4270 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4276 DEBUG(3,("%s becoming a daemon\n",timestring()));
4280 if (open_sockets(is_daemon
,port
))
4282 /* possibly reload the services file. */
4283 reload_services(True
);
4285 maxxmit
= MIN(lp_maxxmit(),BUFFER_SIZE
);
4289 if (sys_chroot(lp_rootdir()) == 0)
4290 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4296 exit_server("normal exit");