Initial version imported to CVS
[Samba.git] / source / smbd / server.c
blob5d8facef33fb5adb819909d202384cecd2e87202
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
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.
22 #include "includes.h"
23 #include "loadparm.h"
24 #include "pcap.h"
25 #include "trans2.h"
26 #include "reply.h"
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;
37 int initial_uid = 0;
38 int initial_gid = 0;
40 BOOL share_mode_pending = False;
42 /* have I done a become_user? */
43 static struct {
44 int cnum, uid;
45 } last_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)
53 extern pstring scope;
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];
68 extern int Protocol;
70 int maxxmit = BUFFER_SIZE;
72 int chain_size = 0;
74 /* a fnum to use when chaining */
75 int chain_fnum = -1;
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;
85 int unix_ERR_code=0;
88 extern int extra_time_offset;
90 extern pstring myhostname;
91 extern struct in_addr myip;
94 static int find_free_connection(int hash);
96 #ifdef SMB_PASSWD
97 extern void generate_next_challenge(char *challenge);
98 extern void set_challenge(char *challenge);
99 #endif
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))
132 result |= S_IXUSR;
134 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
135 result |= S_IXGRP;
137 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
138 result |= S_IXOTH;
140 result &= CREATE_MODE(cnum);
141 return(result);
145 /****************************************************************************
146 change a unix mode to a dos mode
147 ****************************************************************************/
148 int dos_mode(int cnum,char *path,struct stat *sbuf)
150 int result = 0;
152 #if OLD_DOS_MODE
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))))
161 result |= aRONLY;
162 #else
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))))
170 result |= aRONLY;
171 } else {
172 if ((sbuf->st_mode & S_IWUSR) == 0)
173 result |= aRONLY;
175 #endif
177 if ((sbuf->st_mode & S_IXUSR) != 0)
178 result |= aARCH;
180 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
181 result |= aSYSTEM;
183 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
184 result |= aHIDDEN;
186 if (S_ISDIR(sbuf->st_mode))
187 result = aDIR | (result & aRONLY);
189 #if LINKS_READ_ONLY
190 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
191 result |= aRONLY;
192 #endif
194 /* hide files with a name starting with a . */
195 if (lp_hide_dot_files(SNUM(cnum)))
197 char *p = strrchr(path,'/');
198 if (p)
199 p++;
200 else
201 p = path;
203 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
204 result |= aHIDDEN;
207 return(result);
211 /*******************************************************************
212 chmod a file - but preserve some bits
213 ********************************************************************/
214 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
216 struct stat st1;
217 int mask=0;
218 int tmp;
219 int unixmode;
221 if (!st) {
222 st = &st1;
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 */
236 #ifdef S_ISVTX
237 mask |= S_ISVTX;
238 #endif
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);
250 unixmode |= tmp;
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);
258 unixmode |= tmp;
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())
278 BOOL ret;
279 name1[l1-1] = 0;
280 ret = fname_equal(name1,name2);
281 name1[l1-1] = '.';
282 return(ret);
285 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
287 BOOL ret;
288 name2[l2-1] = 0;
289 ret = fname_equal(name1,name2);
290 name2[l2-1] = '.';
291 return(ret);
294 /* now normal filename handling */
295 if (case_sensitive)
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)
307 pstring tmpname;
309 if (is_8_3(name2))
310 return(False);
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)
326 void *cur_dir;
327 char *dname;
328 BOOL mangled;
329 fstring name2;
331 mangled = is_mangled(name);
333 /* handle null paths */
334 if (*path == 0)
335 path = ".";
337 if (docache && (dname = DirCacheCheck(path,name,snum))) {
338 strcpy(name, dname);
339 return(True);
342 if (mangled)
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));
349 return(False);
352 /* now scan for matching names */
353 while ((dname = ReadDirName(cur_dir)))
355 if (*dname == '.' &&
356 (strequal(dname,".") || strequal(dname,"..")))
357 continue;
359 strcpy(name2,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);
367 strcpy(name, dname);
368 CloseDir(cur_dir);
369 return(True);
373 CloseDir(cur_dir);
374 return(False);
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
380 changes etc.
382 We assume that we have already done a chdir() to the right "root" directory
383 for this service.
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)
390 struct stat st;
391 char *start, *end;
392 pstring dirpath;
394 *dirpath = 0;
396 /* convert to basic unix format - removing \ chars and cleaning it up */
397 unix_format(name);
398 unix_clean_name(name);
400 if (!case_sensitive &&
401 (!case_preserve || (is_8_3(name) && !short_case_preserve)))
402 strnorm(name);
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))
413 fstring name2;
414 sprintf(name2,"%.6s.XXXXXX",remote_machine);
415 strcpy(name,(char *)mktemp(name2));
417 return(True);
420 /* stat the name - if it exists then we are all done! */
421 if (sys_stat(name,&st) == 0)
422 return(True);
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)
430 return(False);
432 /* now we need to recursively match the name against the real
433 directory structure */
435 start = name;
436 while (strncmp(start,"./",2) == 0)
437 start += 2;
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 */
447 if (end) *end = 0;
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));
458 *end = '/';
459 return(False);
462 else
464 pstring rest;
466 *rest = 0;
468 /* remember the rest of the pathname so it can be restored
469 later */
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))
477 if (end)
479 /* an intermediate part of the name can't be found */
480 DEBUG(5,("Intermediate not found %s\n",start));
481 *end = '/';
482 return(False);
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
488 purposes */
489 /* if the filename is of mixed case then don't normalise it */
490 if (!case_preserve &&
491 (!strhasupper(start) || !strhaslower(start)))
492 strnorm(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));
500 return(True);
503 /* restore the rest of the string */
504 if (end)
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 */
516 if (end) *end = '/';
519 /* the name has been resolved */
520 DEBUG(5,("conversion finished %s\n",name));
521 return(True);
527 #ifdef QUOTAS
528 #ifdef LINUX
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)
539 uid_t euser_id;
540 struct dqblk D;
541 struct stat S;
542 dev_t devno ;
543 struct mntent *mnt;
544 FILE *fp;
545 int found ;
546 int qcmd, fd ;
547 char *qfpathname;
549 /* find the block device file */
551 if ( stat(path, &S) == -1 )
552 return(False) ;
554 devno = S.st_dev ;
556 fp = setmntent(MOUNTED,"r");
557 found = False ;
559 while ((mnt = getmntent(fp)) != (struct mntent *) 0) {
560 if ( stat(mnt->mnt_dir,&S) == -1 )
561 continue ;
562 if (S.st_dev == devno) {
563 found = True ;
564 break ;
567 endmntent(fp) ;
569 if ( ! found )
570 return(False) ;
572 qcmd = QCMD(Q_GETQUOTA, USRQUOTA);
574 if (hasmntopt(mnt, MNTOPT_NOAUTO) || hasmntopt(mnt, MNTOPT_NOQUOTA))
575 return(False) ;
577 if (!hasquota(mnt, USRQUOTA, &qfpathname))
578 return(False) ;
580 euser_id = geteuid();
581 seteuid(0);
583 if (quotactl(qcmd, mnt->mnt_fsname, euser_id, (caddr_t)&D) != 0) {
584 if ((fd = open(qfpathname, O_RDONLY)) < 0) {
585 seteuid(euser_id);
586 return(False);
588 lseek(fd, (long) dqoff(euser_id), L_SET);
589 switch (read(fd, &D, sizeof(struct dqblk))) {
590 case 0:/* EOF */
591 memset((caddr_t)&D, 0, sizeof(struct dqblk));
592 break;
593 case sizeof(struct dqblk): /* OK */
594 break;
595 default: /* ERROR */
596 close(fd);
597 seteuid(euser_id);
598 return(False);
601 seteuid(euser_id);
602 *bsize=1024;
604 if (D.dqb_bsoftlimit==0)
605 return(False);
606 if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curinodes>D.dqb_isoftlimit))
608 *dfree = 0;
609 *dsize = D.dqb_curblocks;
611 else {
612 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
613 *dsize = D.dqb_bsoftlimit;
615 return (True);
617 #else
618 #ifndef CRAY
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;
625 int r;
626 char dev_disk[256];
627 struct dqblk D;
628 struct stat S;
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();
635 #ifdef USE_SETRES
636 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
637 user_id = getuid();
638 setresuid(euser_id,-1,-1);
639 #endif
640 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
641 #ifdef USE_SETRES
642 if (setresuid(user_id,-1,-1))
643 DEBUG(5,("Unable to reset uid to %d\n", user_id));
644 #endif
645 /* Use softlimit to determine disk space, except when it has been exceeded */
646 *bsize = 1024;
647 if (r)
649 if (errno == EDQUOT)
651 *dfree =0;
652 *dsize =D.dqb_curblocks;
653 return (True);
655 else return(False);
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))
660 *dfree = 0;
661 *dsize = D.dqb_curblocks;
663 else {
664 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
665 *dsize = D.dqb_bsoftlimit;
667 return (True);
669 #else
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)
675 struct mntent *mnt;
676 FILE *fd;
677 struct stat sbuf;
678 dev_t devno ;
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 ;
684 int found ;
686 if ( stat(path,&sbuf) == -1 )
687 return(False) ;
689 devno = sbuf.st_dev ;
691 if ( devno != devno_cached ) {
693 devno_cached = devno ;
695 if ((fd = setmntent(KMTAB)) == NULL)
696 return(False) ;
698 found = False ;
700 while ((mnt = getmntent(fd)) != NULL) {
702 if ( stat(mnt->mnt_dir,&sbuf) == -1 )
703 continue ;
705 if (sbuf.st_dev == devno) {
707 found = True ;
708 break ;
714 strcpy(name,mnt->mnt_dir) ;
715 endmntent(fd) ;
717 if ( ! found )
718 return(False) ;
721 request.qf_magic = QF_MAGIC ;
722 request.qf_entry.id = geteuid() ;
724 if (quotactl(name, Q_GETQUOTA, &request) == -1)
725 return(False) ;
727 if ( ! request.user )
728 return(False) ;
730 if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
732 if ( ! quota_default ) {
734 if ( quotactl(name, Q_GETHEADER, &header) == -1 )
735 return(False) ;
736 else
737 quota_default = header.user_h.def_fq ;
740 *dfree = quota_default ;
742 }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
744 *dfree = 0 ;
746 }else{
748 *dfree = request.qf_entry.user_q.f_quota ;
752 *dsize = request.qf_entry.user_q.f_use ;
754 if ( *dfree )
755 *dfree -= *dsize ;
757 if ( *dfree < 0 )
758 *dfree = 0 ;
760 *bsize = 4096 ; /* Cray blocksize */
762 return(True) ;
765 #endif /* CRAY */
766 #endif /* LINUX */
767 #endif /* QUOTAS */
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();
777 if (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
782 applications getting
783 div by 0 errors */
786 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
788 *dfree /= 2;
789 *dsize /= 2;
790 *bsize *= 2;
791 if (*bsize > WORDMAX )
793 *bsize = WORDMAX;
794 if (*dsize > WORDMAX)
795 *dsize = WORDMAX;
796 if (*dfree > WORDMAX)
797 *dfree = WORDMAX;
798 break;
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();
809 #ifndef NO_STATFS
810 #ifdef USE_STATVFS
811 struct statvfs fs;
812 #else
813 #ifdef ULTRIX
814 struct fs_data fs;
815 #else
816 struct statfs fs;
817 #endif
818 #endif
819 #endif
821 #ifdef QUOTAS
822 if (disk_quotas(path, bsize, dfree, dsize))
824 disk_norm(bsize,dfree,dsize);
825 return(((*bsize)/1024)*(*dfree));
827 #endif
830 /* possibly use system() to get the result */
831 if (df_command && *df_command)
833 int ret;
834 pstring syscmd;
835 pstring outfile;
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");
846 *dsize = 0;
847 *dfree = 0;
848 *bsize = 1024;
849 if (f)
851 fscanf(f,"%d %d %d",dsize,dfree,bsize);
852 fclose(f);
854 else
855 DEBUG(0,("Can't open %s\n",outfile));
858 unlink(outfile);
859 disk_norm(bsize,dfree,dsize);
860 return(((*bsize)/1024)*(*dfree));
863 #ifdef NO_STATFS
864 DEBUG(1,("Warning - no statfs function\n"));
865 return(1);
866 #else
867 #ifdef STATFS4
868 if (statfs(path,&fs,sizeof(fs),0) != 0)
869 #else
870 #ifdef USE_STATVFS
871 if (statvfs(path, &fs))
872 #else
873 #ifdef STATFS3
874 if (statfs(path,&fs,sizeof(fs)) == -1)
875 #else
876 if (statfs(path,&fs) == -1)
877 #endif /* STATFS3 */
878 #endif /* USE_STATVFS */
879 #endif /* STATFS4 */
881 DEBUG(3,("dfree call failed code errno=%d\n",errno));
882 *bsize = 1024;
883 *dfree = 1;
884 *dsize = 1;
885 return(((*bsize)/1024)*(*dfree));
888 #ifdef ULTRIX
889 *bsize = 1024;
890 *dfree = fs.fd_req.bfree;
891 *dsize = fs.fd_req.btot;
892 #else
893 #ifdef USE_STATVFS
894 *bsize = fs.f_frsize;
895 #else
896 #ifdef USE_F_FSIZE
897 /* eg: osf1 has f_fsize = fundamental filesystem block size,
898 f_bsize = optimal transfer block size (MX: 94-04-19) */
899 *bsize = fs.f_fsize;
900 #else
901 *bsize = fs.f_bsize;
902 #endif /* STATFS3 */
903 #endif /* USE_STATVFS */
905 #ifdef STATFS4
906 *dfree = fs.f_bfree;
907 #else
908 *dfree = fs.f_bavail;
909 #endif /* STATFS4 */
910 *dsize = fs.f_blocks;
911 #endif /* ULTRIX */
913 #if defined(SCO) || defined(ISC) || defined(MIPS)
914 *bsize = 512;
915 #endif
917 /* handle rediculous bsize values - some OSes are broken */
918 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
920 disk_norm(bsize,dfree,dsize);
922 if (*bsize < 256)
923 *bsize = 512;
924 if ((*dsize)<1)
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));
931 #endif
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)
954 BOOL ret;
956 errno = 0;
958 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
959 if (!ret)
960 DEBUG(5,("check_name on %s failed\n",name));
962 return(ret);
965 /****************************************************************************
966 check a filename - possibly caling reducename
967 ****************************************************************************/
968 static void check_for_pipe(char *fname)
970 /* special case of pipe opens */
971 char s[10];
972 StrnCpy(s,fname,9);
973 strlower(s);
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 /****************************************************************************
984 open a file
985 ****************************************************************************/
986 void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
988 pstring fname;
990 Files[fnum].open = False;
991 Files[fnum].fd = -1;
992 errno = EPERM;
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);
1001 return;
1004 /* this handles a bug in Win95 - it doesn't say to create the file when it
1005 should */
1006 if (Connections[cnum].printer)
1007 flags |= O_CREAT;
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))
1018 sys_unlink(fname);
1019 #endif
1022 Files[fnum].fd = sys_open(fname,flags,mode);
1024 if ((Files[fnum].fd>=0) &&
1025 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1026 pstring dname;
1027 int dum1,dum2,dum3;
1028 char *p;
1029 strcpy(dname,fname);
1030 p = strrchr(dname,'/');
1031 if (p) *p = 0;
1032 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1033 lp_minprintspace(SNUM(cnum))) {
1034 close(Files[fnum].fd);
1035 Files[fnum].fd = -1;
1036 sys_unlink(fname);
1037 errno = ENOSPC;
1038 return;
1043 /* Fix for files ending in '.' */
1044 if((Files[fnum].fd == -1) && (errno == ENOENT) &&
1045 (strchr(fname,'.')==NULL))
1047 strcat(fname,".");
1048 Files[fnum].fd = sys_open(fname,flags,mode);
1051 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
1052 if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG))
1054 int max_len;
1055 char *p = strrchr(fname, '/');
1057 if (p == fname) /* name is "/xxx" */
1059 max_len = pathconf("/", _PC_NAME_MAX);
1060 p++;
1062 else if ((p == NULL) || (p == fname))
1064 p = fname;
1065 max_len = pathconf(".", _PC_NAME_MAX);
1067 else
1069 *p = '\0';
1070 max_len = pathconf(fname, _PC_NAME_MAX);
1071 *p = '/';
1072 p++;
1074 if (strlen(p) > max_len)
1076 char tmp = p[max_len];
1078 p[max_len] = '\0';
1079 if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1)
1080 p[max_len] = tmp;
1083 #endif
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);
1090 return;
1093 if (Files[fnum].fd >= 0)
1095 struct stat st;
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
1119 * postscript file.
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));
1137 #if USE_MMAP
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;
1151 #endif
1154 /*******************************************************************
1155 sync a file
1156 ********************************************************************/
1157 void sync_file(int fnum)
1159 #ifndef NO_FSYNC
1160 fsync(Files[fnum].fd);
1161 #endif
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)))
1170 return;
1172 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1175 char *p;
1176 if (!(p = strrchr(Files[fnum].name,'/')))
1177 p = Files[fnum].name;
1178 else
1179 p++;
1181 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1182 return;
1186 int ret;
1187 pstring magic_output;
1188 pstring fname;
1189 strcpy(fname,Files[fnum].name);
1191 if (*lp_magicoutput(SNUM(cnum)))
1192 strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1193 else
1194 sprintf(magic_output,"%s.out",fname);
1196 chmod(fname,0755);
1197 ret = smbrun(fname,magic_output);
1198 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1199 unlink(fname);
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;
1219 #if USE_MMAP
1220 if(Files[fnum].mmap_ptr)
1222 munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
1223 Files[fnum].mmap_ptr = NULL;
1225 #endif
1227 if (lp_share_modes(SNUM(cnum)))
1228 del_share_mode(fnum);
1230 if (Files[fnum].modified) {
1231 struct stat st;
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)
1244 print_file(fnum);
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())
1266 return(AALL);
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"))
1279 return(AREAD);
1282 return(AFAIL);
1285 switch (new_deny)
1287 case DENY_WRITE:
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);
1291 return(AFAIL);
1292 case DENY_READ:
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);
1296 return(AFAIL);
1297 case DENY_NONE:
1298 if (old_deny==DENY_WRITE) return(AREAD);
1299 if (old_deny==DENY_READ) return(AWRITE);
1300 if (old_deny==DENY_NONE) return(AALL);
1301 return(AFAIL);
1303 return(AFAIL);
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)
1312 int pid=0;
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? */
1322 return(False);
1325 /****************************************************************************
1326 C. Hoch 11/22/95
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)){
1334 close_file(fnum);
1335 errno = EACCES;
1336 unix_ERR_class = ERRDOS;
1337 unix_ERR_code = ERRlock;
1339 else
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)
1351 int flags=0;
1352 int flags2=0;
1353 int deny_mode = (share_mode>>4)&7;
1354 struct stat sbuf;
1355 BOOL file_existed = file_exist(fname,&sbuf);
1356 BOOL fcbopen = False;
1357 int share_pid=0;
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;
1366 return;
1369 if ((ofun & 0x3) == 0 && file_existed) {
1370 errno = EEXIST;
1371 return;
1374 if (ofun & 0x10)
1375 flags2 |= O_CREAT;
1376 if ((ofun & 0x3) == 2)
1377 flags2 |= O_TRUNC;
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)
1384 case 1:
1385 flags = O_WRONLY;
1386 break;
1387 case 0xF:
1388 fcbopen = True;
1389 flags = O_RDWR;
1390 break;
1391 case 2:
1392 flags = O_RDWR;
1393 break;
1394 default:
1395 flags = O_RDONLY;
1396 break;
1399 if (flags != O_RDONLY && file_existed &&
1400 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
1401 if (!fcbopen) {
1402 errno = EACCES;
1403 return;
1405 flags = O_RDONLY;
1408 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
1409 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1410 errno = EINVAL;
1411 return;
1414 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1416 if (lp_share_modes(SNUM(cnum))) {
1417 int old_share=0;
1419 if (file_existed)
1420 old_share = get_share_mode(cnum,&sbuf,&share_pid);
1422 if (share_pid) {
1423 /* someone else has a share lock on it, check to see
1424 if we can too */
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));
1431 errno = EACCES;
1432 unix_ERR_class = ERRDOS;
1433 unix_ERR_code = ERRbadshare;
1434 return;
1438 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1439 share_pid,fname);
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,
1446 share_pid,fname,
1447 access_allowed));
1448 errno = EACCES;
1449 unix_ERR_class = ERRDOS;
1450 unix_ERR_code = ERRbadshare;
1451 return;
1454 if (access_allowed == AREAD)
1455 flags = O_RDONLY;
1457 if (access_allowed == AWRITE)
1458 flags = O_WRONLY;
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) {
1468 flags = O_RDONLY;
1469 open_file(fnum,cnum,fname,flags,mode);
1472 if (Files[fnum].open) {
1473 int open_mode=0;
1474 switch (flags) {
1475 case O_RDONLY:
1476 open_mode = 0;
1477 break;
1478 case O_RDWR:
1479 open_mode = 2;
1480 break;
1481 case O_WRONLY:
1482 open_mode = 1;
1483 break;
1486 Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1487 Files[fnum].share_pending = True;
1489 if (Access) {
1490 (*Access) = open_mode;
1493 if (action) {
1494 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1495 if (!file_existed) *action = 2;
1496 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1499 if (!share_pid)
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)
1514 int i;
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))) {
1518 int pid=0;
1519 get_share_mode_by_fnum(Files[i].cnum,i,&pid);
1520 if (!pid) {
1521 set_share_mode(i,Files[i].share_mode);
1522 Files[i].share_pending = False;
1524 } else {
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)
1536 int offset = 0;
1537 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1538 offset = 3;
1540 Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
1541 return(Files[fnum].pos);
1544 /****************************************************************************
1545 read from a file
1546 ****************************************************************************/
1547 int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact)
1549 int ret=0;
1551 if (!Files[fnum].can_write)
1553 ret = read_predict(Files[fnum].fd,
1554 pos,
1555 data,
1556 NULL,
1557 maxcnt);
1559 data += ret;
1560 maxcnt -= ret;
1561 mincnt = MAX(mincnt-ret,0);
1562 pos += ret;
1565 #if USE_MMAP
1566 if (Files[fnum].mmap_ptr)
1568 int num = MIN(maxcnt,Files[fnum].mmap_size-pos);
1569 if (num > 0)
1571 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1572 data += num;
1573 pos += num;
1574 maxcnt -= num;
1575 mincnt = MAX(mincnt-num,0);
1576 ret += num;
1579 #endif
1581 if (maxcnt <= 0)
1582 return(ret);
1584 if (seek_file(fnum,pos) != pos)
1586 DEBUG(3,("Failed to seek to %d\n",pos));
1587 return(ret);
1590 if (maxcnt > 0)
1591 ret += read_with_timeout(Files[fnum].fd,
1592 data,
1593 mincnt,
1594 maxcnt,
1595 timeout,
1596 exact);
1598 return(ret);
1602 /****************************************************************************
1603 write to a file
1604 ****************************************************************************/
1605 int write_file(int fnum,char *data,int n)
1607 if (!Files[fnum].can_write) {
1608 errno = EPERM;
1609 return(0);
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;
1627 int snum;
1629 if (!OPEN_CNUM(cnum))
1631 last_cnum = -1;
1632 return(False);
1635 Connections[cnum].lastused = smb_last_time;
1637 snum = SNUM(cnum);
1639 if (do_chdir &&
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));
1645 return(False);
1648 if (cnum == last_cnum)
1649 return(True);
1651 last_cnum = 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);
1660 return(True);
1664 /****************************************************************************
1665 become the specified uid
1666 ****************************************************************************/
1667 static BOOL become_uid(int uid)
1669 if (initial_uid != 0)
1670 return(True);
1672 #ifdef AIX
1674 /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */
1675 priv_t priv;
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)"));
1685 #endif
1687 #ifdef USE_SETRES
1688 if (setresuid(-1,uid,-1) != 0)
1689 #else
1690 if ((seteuid(uid) != 0) &&
1691 (setuid(uid) != 0))
1692 #endif
1694 DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n",
1695 uid,getuid(), geteuid()));
1696 if (uid > 32000)
1697 DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n"));
1698 return(False);
1701 if (((uid == -1) || (uid == 65535)) && geteuid() != uid)
1703 DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n"));
1704 return(False);
1707 return(True);
1711 /****************************************************************************
1712 become the specified gid
1713 ****************************************************************************/
1714 static BOOL become_gid(int gid)
1716 if (initial_uid != 0)
1717 return(True);
1719 #ifdef USE_SETRES
1720 if (setresgid(-1,gid,-1) != 0)
1721 #else
1722 if (setgid(gid) != 0)
1723 #endif
1725 DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n",
1726 gid,getgid(),getegid()));
1727 if (gid > 32000)
1728 DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n"));
1729 return(False);
1732 return(True);
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)
1749 BOOL ret;
1750 static struct passwd *pass=NULL;
1752 if (initial_uid != 0)
1753 return(True);
1755 if (!pass)
1756 pass = Get_Pwnam(lp_guestaccount(-1),True);
1757 if (!pass) return(False);
1759 ret = become_id(pass->pw_uid,pass->pw_gid);
1761 if (!ret)
1762 DEBUG(1,("Failed to become guest. Invalid guest account?\n"));
1764 last_user.cnum = -2;
1766 return(ret);
1769 /*******************************************************************
1770 check if a username is OK
1771 ********************************************************************/
1772 static BOOL check_user_ok(int cnum,user_struct *vuser,int snum)
1774 int i;
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++;
1786 return(True);
1790 /****************************************************************************
1791 become the user of a connection number
1792 ****************************************************************************/
1793 BOOL become_user(int cnum, int uid)
1795 int new_umask;
1796 user_struct *vuser;
1797 int snum,gid;
1798 int ngroups;
1799 gid_t *groups;
1801 if (last_user.cnum == cnum && last_user.uid == uid) {
1802 DEBUG(4,("Skipping become_user - already user\n"));
1803 return(True);
1806 unbecome_user();
1808 if (!OPEN_CNUM(cnum)) {
1809 DEBUG(2,("Connection %d not open\n",cnum));
1810 return(False);
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;
1823 } else {
1824 if (!vuser) {
1825 DEBUG(2,("Invalid vuid used %d\n",uid));
1826 return(False);
1828 uid = vuser->uid;
1829 if(!*lp_force_group(snum))
1830 gid = vuser->gid;
1831 else
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 */
1844 if (ngroups > 0)
1845 if (setgroups(ngroups,groups)<0)
1846 DEBUG(0,("setgroups call failed!\n"));
1848 #endif
1850 if (!Connections[cnum].admin_user && !become_uid(uid))
1851 return(False);
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));
1863 return(True);
1866 /****************************************************************************
1867 unbecome the user of a connection number
1868 ****************************************************************************/
1869 BOOL unbecome_user(void )
1871 if (last_user.cnum == -1)
1872 return(False);
1874 ChDir(OriginalDir);
1876 umask(old_umask);
1878 if (initial_uid == 0)
1880 #ifdef USE_SETRES
1881 setresuid(-1,getuid(),-1);
1882 setresgid(-1,getgid(),-1);
1883 #else
1884 if (seteuid(initial_uid) != 0)
1885 setuid(initial_uid);
1886 setgid(initial_gid);
1887 #endif
1889 #ifdef NO_EID
1890 if (initial_uid == 0)
1891 DEBUG(2,("Running with no EID\n"));
1892 initial_uid = getuid();
1893 initial_gid = getgid();
1894 #else
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();
1905 #endif
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;
1916 return(True);
1919 /****************************************************************************
1920 find a service entry
1921 ****************************************************************************/
1922 int find_service(char *service)
1924 int iService;
1926 string_sub(service,"\\","/");
1928 iService = lp_servicenumber(service);
1930 /* now handle the special case of a home directory */
1931 if (iService < 0)
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)"));
1936 if (phome_dir)
1938 int iHomeService;
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. */
1948 if (iService < 0)
1950 int iPrinterService;
1952 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1954 char *pszTemp;
1956 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1957 pszTemp = PRINTCAP;
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);
1964 if (iService < 0)
1965 DEBUG(0,("failed to add %s as a printer service!\n", service));
1967 else
1968 DEBUG(3,("%s is not a valid printer name\n", service));
1972 /* just possibly it's a default service? */
1973 if (iService < 0)
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);
1985 if (iService >= 0)
1986 if (!VALID_SNUM(iService))
1988 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1989 iService = -1;
1992 if (iService < 0)
1993 DEBUG(3,("find_service() failed to find service %s\n", service));
1995 return (iService);
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);
2016 struct
2018 int unixerror;
2019 int smbclass;
2020 int smbcode;
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},
2033 #ifdef EDQUOT
2034 {EDQUOT,ERRHRD,ERRdiskfull},
2035 #endif
2036 #ifdef ENOTEMPTY
2037 {ENOTEMPTY,ERRDOS,ERRnoaccess},
2038 #endif
2039 #ifdef EXDEV
2040 {EXDEV,ERRDOS,ERRdiffdevice},
2041 #endif
2042 {EROFS,ERRHRD,ERRnowrite},
2043 {0,0,0}
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;
2053 int ecode=def_code;
2054 int i=0;
2056 if (unix_ERR_class != SUCCESS)
2058 eclass = unix_ERR_class;
2059 ecode = unix_ERR_code;
2060 unix_ERR_class = SUCCESS;
2061 unix_ERR_code = 0;
2063 else
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;
2071 break;
2073 i++;
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);
2087 int cmd;
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",
2094 timestring(),
2095 line,
2096 (int)CVAL(inbuf,smb_com),
2097 smb_fn_name(CVAL(inbuf,smb_com)),
2098 error_class,
2099 error_code));
2101 if (errno != 0)
2102 DEBUG(3,("error string = %s\n",strerror(errno)));
2104 return(outsize);
2108 #ifndef SIGCLD_IGNORE
2109 /****************************************************************************
2110 this prevents zombie child processes
2111 ****************************************************************************/
2112 static int sig_cld()
2114 static int depth = 0;
2115 if (depth != 0)
2117 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2118 depth=0;
2119 return(0);
2121 depth++;
2123 BlockSignals(True);
2124 DEBUG(5,("got SIGCLD\n"));
2126 #ifdef USE_WAITPID
2127 while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2128 #endif
2130 /* Stop zombies */
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);
2140 #else
2141 signal(SIGCLD, SIGNAL_CAST sig_cld);
2142 #endif
2143 #endif
2145 #ifndef USE_WAITPID
2146 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
2147 #endif
2148 depth--;
2149 BlockSignals(False);
2150 return 0;
2152 #endif
2154 /****************************************************************************
2155 this is called when the client exits abruptly
2156 **************************************************************************/
2157 static int sig_pipe()
2159 exit_server("Got sigpipe\n");
2160 return(0);
2163 /****************************************************************************
2164 open the socket communication
2165 ****************************************************************************/
2166 static BOOL open_sockets(BOOL is_daemon,int port)
2168 extern int Client;
2170 if (is_daemon)
2172 int s;
2173 struct sockaddr addr;
2174 int in_addrlen = sizeof(addr);
2176 /* Stop zombies */
2177 #ifdef SIGCLD_IGNORE
2178 signal(SIGCLD, SIG_IGN);
2179 #else
2180 signal(SIGCLD, SIGNAL_CAST sig_cld);
2181 #endif
2183 /* open an incoming socket */
2184 s = open_socket_in(SOCK_STREAM, port, 0);
2185 if (s == -1)
2186 return(False);
2188 /* ready to listen */
2189 if (listen(s, 5) == -1)
2191 DEBUG(0,("listen: %s",strerror(errno)));
2192 close(s);
2193 return False;
2196 /* now accept incoming connections - forking a new process
2197 for each incoming connection */
2198 DEBUG(2,("waiting for a connection\n"));
2199 while (1)
2201 Client = accept(s,&addr,&in_addrlen);
2203 if (Client == -1 && errno == EINTR)
2204 continue;
2206 if (Client == -1)
2208 DEBUG(0,("accept: %s",strerror(errno)));
2209 return False;
2212 #ifdef NO_FORK_DEBUG
2213 #ifndef NO_SIGNAL_TEST
2214 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2215 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2216 #endif
2217 return True;
2218 #else
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);
2224 #endif
2225 /* close our standard file descriptors */
2226 close_low_fds();
2228 set_socket_options(Client,"SO_KEEPALIVE");
2229 set_socket_options(Client,user_socket_options);
2231 return True;
2233 close(Client); /* The parent doesn't need this socket */
2234 #endif
2237 else
2239 /* We will abort gracefully when the client or remote system
2240 goes away */
2241 #ifndef NO_SIGNAL_TEST
2242 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2243 #endif
2244 Client = dup(0);
2246 /* close our standard file descriptors */
2247 close_low_fds();
2249 set_socket_options(Client,"SO_KEEPALIVE");
2250 set_socket_options(Client,user_socket_options);
2253 return True;
2257 /****************************************************************************
2258 check if a snum is in use
2259 ****************************************************************************/
2260 BOOL snum_used(int snum)
2262 int i;
2263 for (i=0;i<MAX_CONNECTIONS;i++)
2264 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2265 return(True);
2266 return(False);
2269 /****************************************************************************
2270 reload the services file
2271 **************************************************************************/
2272 BOOL reload_services(BOOL test)
2274 BOOL ret;
2276 if (lp_loaded())
2278 pstring fname;
2279 strcpy(fname,lp_configfile());
2280 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2282 strcpy(servicesf,fname);
2283 test = False;
2287 reopen_logs();
2289 if (test && !lp_file_list_changed())
2290 return(True);
2292 lp_killunused(snum_used);
2294 ret = lp_load(servicesf,False);
2296 /* perhaps the config filename is now set */
2297 if (!test)
2298 reload_services(True);
2300 reopen_logs();
2303 extern int Client;
2304 if (Client != -1) {
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);
2315 return(ret);
2320 /****************************************************************************
2321 this prevents zombie child processes
2322 ****************************************************************************/
2323 static int sig_hup()
2325 BlockSignals(True);
2326 DEBUG(0,("Got SIGHUP\n"));
2327 reload_services(False);
2328 #ifndef DONT_REINSTALL_SIG
2329 signal(SIGHUP,SIGNAL_CAST sig_hup);
2330 #endif
2331 BlockSignals(False);
2332 return(0);
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))
2343 if (getuid() == 0)
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));
2350 else
2352 int i,ngroups;
2353 int *igroups;
2354 gid_t grp = 0;
2355 ngroups = getgroups(0,&grp);
2356 if (ngroups <= 0)
2357 ngroups = 32;
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)
2364 ngroups = 0;
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 */
2373 if (ngroups > 0)
2375 /* does getgroups return ints or gid_t ?? */
2376 static BOOL groups_use_ints = True;
2378 if (groups_use_ints &&
2379 ngroups == 1 &&
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;
2392 else
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]));
2405 DEBUG(3,("\n"));
2407 return 0;
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)
2415 int cnum;
2416 int snum;
2417 struct passwd *pass = NULL;
2418 connection_struct *pcon;
2419 BOOL guest = False;
2420 BOOL force = False;
2421 static BOOL first_connection = True;
2423 strlower(service);
2425 snum = find_service(service);
2426 if (snum < 0)
2428 if (strequal(service,"IPC$"))
2430 DEBUG(3,("%s refusing IPC connection\n",timestring()));
2431 return(-3);
2434 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
2435 return(-2);
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)) {
2451 return(-4);
2454 /* you can only connect to the IPC$ service as an ipc device */
2455 if (strequal(service,"IPC$"))
2456 strcpy(dev,"IPC");
2458 if (*dev == '?' || !*dev)
2460 if (lp_print_ok(snum))
2461 strcpy(dev,"LPT1:");
2462 else
2463 strcpy(dev,"A:");
2466 /* if the request is as a printer and you can't print then refuse */
2467 strupper(dev);
2468 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2469 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2470 return(-6);
2473 /* lowercase the user name */
2474 strlower(user);
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));
2483 return(-1);
2486 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2487 if (cnum < 0)
2489 DEBUG(0,("%s couldn't find free connection\n",timestring()));
2490 return(-1);
2493 pcon = &Connections[cnum];
2494 bzero((char *)pcon,sizeof(*pcon));
2496 /* find out some info about the user */
2497 pass = Get_Pwnam(user,True);
2499 if (pass == NULL)
2501 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
2502 return(-7);
2505 pcon->read_only = lp_readonly(snum);
2508 pstring list;
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)) &&
2524 !pcon->read_only)
2526 pcon->admin_user = True;
2527 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2529 else
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;
2538 pcon->used = True;
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);
2545 #if HAVE_GETGRNAM
2546 if (*lp_force_group(snum))
2548 struct group *gptr = (struct group *)getgrnam(lp_force_group(snum));
2549 if (gptr)
2551 pcon->gid = gptr->gr_gid;
2552 DEBUG(3,("Forced group %s\n",lp_force_group(snum)));
2554 else
2555 DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum)));
2557 #endif
2559 if (*lp_force_user(snum))
2561 struct passwd *pass2;
2562 fstring fuser;
2563 strcpy(fuser,lp_force_user(snum));
2564 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2565 if (pass2)
2567 pcon->uid = pass2->pw_uid;
2568 string_set(&pcon->user,fuser);
2569 strcpy(user,fuser);
2570 pcon->force_user = True;
2571 DEBUG(3,("Forced user %s\n",fuser));
2573 else
2574 DEBUG(1,("Couldn't find user %s\n",fuser));
2578 pstring s;
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 */
2586 pcon->ngroups = 0;
2587 pcon->groups = NULL;
2589 if (!IS_IPC(cnum))
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"));
2600 return(-8);
2603 if (lp_status(SNUM(cnum)))
2604 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2606 first_connection = False;
2607 } /* IS_IPC */
2609 pcon->open = True;
2611 /* execute any "root preexec = " line */
2612 if (*lp_rootpreexec(SNUM(cnum)))
2614 pstring cmd;
2615 strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2616 standard_sub(cnum,cmd);
2617 DEBUG(5,("cmd=%s\n",cmd));
2618 smbrun(cmd,NULL);
2621 if (!become_user(cnum,pcon->uid))
2623 DEBUG(0,("Can't become connected user!\n"));
2624 pcon->open = False;
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);
2631 return(-1);
2634 if (ChDir(pcon->connectpath) != 0)
2636 DEBUG(0,("Can't change directory to %s\n",pcon->connectpath));
2637 pcon->open = False;
2638 unbecome_user();
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);
2645 return(-5);
2648 string_set(&pcon->origpath,pcon->connectpath);
2650 #if SOFTLINK_OPTIMISATION
2651 /* resolve any soft links early */
2653 pstring s;
2654 strcpy(s,pcon->connectpath);
2655 GetWd(s);
2656 string_set(&pcon->connectpath,s);
2657 ChDir(pcon->connectpath);
2659 #endif
2661 num_connections_open++;
2662 add_session_user(user);
2664 /* execute any "preexec = " line */
2665 if (*lp_preexec(SNUM(cnum)))
2667 pstring cmd;
2668 strcpy(cmd,lp_preexec(SNUM(cnum)));
2669 standard_sub(cnum,cmd);
2670 smbrun(cmd,NULL);
2673 /* we've finished with the sensitive stuff */
2674 unbecome_user();
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",
2679 timestring(),
2680 Client_info.name,Client_info.addr,
2681 lp_servicename(SNUM(cnum)),user,
2682 pcon->uid,
2683 pcon->gid,
2684 (int)getpid()));
2687 return(cnum);
2691 /****************************************************************************
2692 find first available file slot
2693 ****************************************************************************/
2694 int find_free_file(void )
2696 int i;
2697 for (i=1;i<MAX_OPEN_FILES;i++)
2698 if (!Files[i].open)
2699 return(i);
2700 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2701 return(-1);
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 )
2711 int i;
2712 BOOL used=False;
2713 hash = (hash % (MAX_CONNECTIONS-2))+1;
2715 again:
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));
2722 return(i);
2724 i++;
2725 if (i == MAX_CONNECTIONS)
2726 i = 1;
2729 if (!used)
2731 used = !used;
2732 goto again;
2735 DEBUG(1,("ERROR! Out of connection structures\n"));
2736 return(-1);
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;
2749 return outsize;
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;
2767 return outsize;
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);
2777 int secword=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);
2786 #ifdef SMB_PASSWD
2787 /* Create a token value and add it to the outgoing packet. */
2788 if (doencrypt)
2789 generate_next_challenge(smb_buf(outbuf));
2790 #endif
2792 Protocol = PROTOCOL_LANMAN1;
2794 if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2795 DEBUG(3,("using password server validation\n"));
2796 #ifdef SMB_PASSWD
2797 if (doencrypt) set_challenge(smb_buf(outbuf));
2798 #endif
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);
2822 int secword=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);
2831 #ifdef SMB_PASSWD
2832 /* Create a token value and add it to the outgoing packet. */
2833 if (doencrypt)
2834 generate_next_challenge(smb_buf(outbuf));
2835 #endif
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"));
2843 #ifdef SMB_PASSWD
2844 if (doencrypt) set_challenge(smb_buf(outbuf));
2845 #endif
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 */
2865 int secword=0;
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;
2873 #ifdef SMB_PASSWD
2874 /* Create a token value and add it to the outgoing packet. */
2875 if (doencrypt) {
2876 generate_next_challenge(smb_buf(outbuf));
2877 /* Tell the nt machine how long the challenge is. */
2878 SSVALS(outbuf,smb_vwv16+1,8);
2880 #endif
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"));
2888 #ifdef SMB_PASSWD
2889 if (doencrypt) set_challenge(smb_buf(outbuf));
2890 #endif
2893 if (lp_readraw() && lp_writeraw())
2894 capabilities |= 1;
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:
2910 WinNT 3.51:
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]
2920 Win95:
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]
2930 OS/2:
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
2942 * MS product.
2943 Protocol WfWg Win95 WinNT OS/2
2944 PC NETWORK PROGRAM 1.0 1 1 1 1
2945 XENIX CORE 2 2
2946 MICROSOFT NETWORKS 3.0 2 2
2947 DOS LM1.2X002 3 3
2948 MICROSOFT NETWORKS 1.03 3
2949 DOS LANMAN2.1 4 4
2950 LANMAN1.0 4 3
2951 Windows for Workgroups 3.1a 5 5 5
2952 LM1.2X002 6 4
2953 LANMAN2.1 7 5
2954 NT LM 0.12 6 8
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 */
2968 struct {
2969 char *proto_name;
2970 char *short_name;
2971 int (*proto_reply_fn)(char *);
2972 int protocol_level;
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},
2983 {NULL,NULL},
2987 /****************************************************************************
2988 reply to a negprot
2989 ****************************************************************************/
2990 static int reply_negprot(char *inbuf,char *outbuf)
2992 extern fstring remote_arch;
2993 int outsize = set_message(outbuf,1,0,True);
2994 int Index=0;
2995 int choice= -1;
2996 int protocol;
2997 char *p;
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))
3004 Index++;
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"))
3019 arch &= ARCH_WINNT;
3020 else if (strcsequal(p,"XENIX CORE"))
3021 arch &= ( ARCH_WINNT | ARCH_OS2 );
3022 else if (strcsequal(p,"Samba")) {
3023 arch = ARCH_SAMBA;
3024 break;
3027 p += strlen(p) + 2;
3030 switch ( arch ) {
3031 case ARCH_SAMBA:
3032 strcpy(remote_arch,"Samba");
3033 break;
3034 case ARCH_WFWG:
3035 strcpy(remote_arch,"WfWg");
3036 break;
3037 case ARCH_WIN95:
3038 strcpy(remote_arch,"Win95");
3039 break;
3040 case ARCH_WINNT:
3041 strcpy(remote_arch,"WinNT");
3042 break;
3043 case ARCH_OS2:
3044 strcpy(remote_arch,"OS2");
3045 break;
3046 default:
3047 strcpy(remote_arch,"UNKNOWN");
3048 break;
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;
3063 Index = 0;
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))
3068 choice = Index;
3069 Index++;
3070 p += strlen(p) + 2;
3072 if(choice != -1)
3073 break;
3076 SSVAL(outbuf,smb_vwv0,choice);
3077 if(choice != -1) {
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));
3084 else {
3085 DEBUG(0,("No protocol supported !\n"));
3087 SSVAL(outbuf,smb_vwv0,choice);
3089 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3091 return(outsize);
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;
3101 char *p2;
3103 DEBUG(4,("parsing connect string %s\n",p));
3105 p2 = strrchr(p,'\\');
3106 if (p2 == NULL)
3107 strcpy(service,p);
3108 else
3109 strcpy(service,p2+1);
3111 p += strlen(p) + 2;
3113 strcpy(password,p);
3114 *pwlen = strlen(password);
3116 p += strlen(p) + 2;
3118 strcpy(dev,p);
3120 *user = 0;
3121 p = strchr(service,'%');
3122 if (p != NULL)
3124 *p = 0;
3125 strcpy(user,p+1);
3130 /****************************************************************************
3131 close all open files for a connection
3132 ****************************************************************************/
3133 static void close_open_files(int cnum)
3135 int i;
3136 for (i=0;i<MAX_OPEN_FILES;i++)
3137 if( Files[i].cnum == cnum && Files[i].open) {
3138 close_file(i);
3144 /****************************************************************************
3145 close a cnum
3146 ****************************************************************************/
3147 void close_cnum(int cnum, int uid)
3149 extern struct from_host Client_info;
3151 DirCacheFlush(SNUM(cnum));
3153 unbecome_user();
3155 if (!OPEN_CNUM(cnum))
3157 DEBUG(0,("Can't close cnum %d\n",cnum));
3158 return;
3161 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3162 timestring(),
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))
3179 pstring cmd;
3180 strcpy(cmd,lp_postexec(SNUM(cnum)));
3181 standard_sub(cnum,cmd);
3182 smbrun(cmd,NULL);
3183 unbecome_user();
3186 unbecome_user();
3187 /* execute any "root postexec = " line */
3188 if (*lp_rootpostexec(SNUM(cnum)))
3190 pstring cmd;
3191 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3192 standard_sub(cnum,cmd);
3193 smbrun(cmd,NULL);
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;
3220 pstring fname;
3221 FILE *f;
3222 int mypid = getpid();
3223 int i;
3225 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3227 if (max_connections <= 0)
3228 return(True);
3230 bzero(&crec,sizeof(crec));
3232 strcpy(fname,lp_lockdir());
3233 standard_sub(cnum,fname);
3234 trim_string(fname,"","/");
3236 strcat(fname,"/");
3237 strcat(fname,name);
3238 strcat(fname,".LCK");
3240 f = fopen(fname,"r+");
3241 if (!f)
3243 DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
3244 return(False);
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));
3255 fclose(f);
3256 return(False);
3258 if (crec.pid == mypid && crec.cnum == cnum)
3259 break;
3262 if (crec.pid != mypid || crec.cnum != cnum)
3264 fclose(f);
3265 DEBUG(2,("Entry not found in lock file %s\n",fname));
3266 return(False);
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)));
3276 fclose(f);
3277 return(False);
3280 DEBUG(3,("Yield successful\n"));
3282 fclose(f);
3283 return(True);
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;
3293 pstring fname;
3294 FILE *f;
3295 int snum = SNUM(cnum);
3296 int i,foundi= -1;
3297 int total_recs;
3299 if (max_connections <= 0)
3300 return(True);
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))
3309 mkdir(fname,0755);
3311 strcat(fname,"/");
3312 strcat(fname,name);
3313 strcat(fname,".LCK");
3315 if (!file_exist(fname,NULL))
3317 f = fopen(fname,"w");
3318 if (f) fclose(f);
3321 total_recs = file_size(fname) / sizeof(crec);
3323 f = fopen(fname,"r+");
3325 if (!f)
3327 DEBUG(1,("couldn't open lock file %s\n",fname));
3328 return(False);
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;
3340 break;
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;
3349 continue;
3351 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3353 foundi=i;
3354 if (!Clear) break;
3358 if (foundi < 0)
3360 DEBUG(3,("no free locks in %s\n",fname));
3361 fclose(f);
3362 return(False);
3365 /* fill in the crec */
3366 bzero((void *)&crec,sizeof(crec));
3367 crec.magic = 0x280267;
3368 crec.pid = getpid();
3369 crec.cnum = cnum;
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);
3381 /* make our mark */
3382 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3383 fwrite(&crec,sizeof(crec),1,f) != 1)
3385 fclose(f);
3386 return(False);
3389 fclose(f);
3390 return(True);
3393 #if DUMP_CORE
3394 /*******************************************************************
3395 prepare to dump a core file - carefully!
3396 ********************************************************************/
3397 static BOOL dump_core(void)
3399 char *p;
3400 pstring dname;
3401 strcpy(dname,debugf);
3402 if ((p=strrchr(dname,'/'))) *p=0;
3403 strcat(dname,"/corefiles");
3404 mkdir(dname,0700);
3405 sys_chown(dname,getuid(),getgid());
3406 chmod(dname,0700);
3407 if (chdir(dname)) return(False);
3408 umask(~(0700));
3410 #ifndef NO_GETRLIMIT
3411 #ifdef RLIMIT_CORE
3413 struct rlimit rlp;
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));
3420 #endif
3421 #endif
3424 DEBUG(0,("Dumping core in %s\n",dname));
3425 return(True);
3427 #endif
3429 /****************************************************************************
3430 exit the server
3431 ****************************************************************************/
3432 void exit_server(char *reason)
3434 static int firsttime=1;
3435 int i;
3437 if (!firsttime) exit(0);
3438 firsttime = 0;
3440 unbecome_user();
3441 DEBUG(2,("Closing connections\n"));
3442 for (i=0;i<MAX_CONNECTIONS;i++)
3443 if (Connections[i].open)
3444 close_cnum(i,-1);
3445 #ifdef DFS_AUTH
3446 if (dcelogin_atmost_once)
3447 dfs_unlogin();
3448 #endif
3449 if (!reason) {
3450 int oldlevel = DEBUGLEVEL;
3451 DEBUGLEVEL = 10;
3452 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3453 if (last_inbuf)
3454 show_msg(last_inbuf);
3455 DEBUGLEVEL = oldlevel;
3456 DEBUG(0,("===============================================================\n"));
3457 #if DUMP_CORE
3458 if (dump_core()) return;
3459 #endif
3461 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
3462 exit(0);
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
3507 int code;
3508 char *name;
3509 int (*fn)();
3510 int flags;
3511 #if PROFILING
3512 unsigned long time;
3513 #endif
3515 smb_messages[] = {
3517 /* CORE PROTOCOL */
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);
3621 int match;
3623 for (match=0;match<num_smb_messages;match++)
3624 if (smb_messages[match].code == type)
3625 break;
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)
3639 static int pid= -1;
3640 int outsize = 0;
3641 static int num_smb_messages =
3642 sizeof(smb_messages) / sizeof(struct smb_message_struct);
3643 int match;
3645 #if PROFILING
3646 struct timeval msg_start_time;
3647 struct timeval msg_end_time;
3648 static unsigned long total_time = 0;
3650 GetTimeOfDay(&msg_start_time);
3651 #endif
3653 if (pid == -1)
3654 pid = getpid();
3656 errno = 0;
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)));
3663 return(-1);
3666 for (match=0;match<num_smb_messages;match++)
3667 if (smb_messages[match].code == type)
3668 break;
3670 if (match == num_smb_messages)
3672 DEBUG(0,("Unknown message type %d!\n",type));
3673 outsize = reply_unknown(inbuf,outbuf);
3675 else
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))
3686 unbecome_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));
3708 last_inbuf = inbuf;
3710 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3712 else
3714 outsize = reply_unknown(inbuf,outbuf);
3718 #if PROFILING
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));
3735 #endif
3737 return(outsize);
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)
3756 int outsize = 0;
3757 char *ibuf,*obuf;
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;
3766 if (was_inchain)
3767 outbuf = last_outbuf;
3768 else
3769 insize_deleted = 0;
3772 insize_deleted = 0;
3773 inbuf2 -= insize_deleted;
3774 insize_remaining = size - PTR_DIFF(inbuf2,inbuf);
3775 insize_deleted += size - (insize_remaining + smb_wct);
3777 in_chain = True;
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);
3785 if (!ibuf || !obuf)
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
3809 means a reply */
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"));
3818 show_msg(ibuf);
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);
3849 int outsize = 0;
3850 int msg_type = CVAL(inbuf,0);
3852 smb_last_time = time(NULL);
3854 chain_size = 0;
3856 bzero(outbuf,smb_size);
3858 if (msg_type != 0)
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
3868 means a reply */
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);
3878 if(outsize > 4)
3879 smb_setlen(outbuf,outsize - 4);
3880 return(outsize);
3884 /****************************************************************************
3885 process commands from the client
3886 ****************************************************************************/
3887 void process(void )
3889 static int trans_num = 0;
3890 int nread;
3891 extern struct from_host Client_info;
3892 extern int Client;
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))
3899 return;
3901 InBuffer += SMB_ALIGNMENT;
3902 OutBuffer += SMB_ALIGNMENT;
3904 #if PRIME_NMBD
3905 DEBUG(3,("priming nmbd\n"));
3907 struct in_addr ip;
3908 ip = *interpret_addr2("localhost");
3909 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
3910 *OutBuffer = 0;
3911 send_one_packet(OutBuffer,1,ip,137,SOCK_DGRAM);
3913 #endif
3915 last_user.cnum = -1;
3917 while (True)
3919 int32 len;
3920 int msg_type;
3921 int msg_flags;
3922 int type;
3923 int deadtime = lp_deadtime()*60;
3924 int counter;
3925 int last_keepalive=0;
3927 if (deadtime <= 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) {
3936 unbecome_user();
3937 if (!unlink(share_del_pending))
3938 DEBUG(3,("Share file deleted %s\n",share_del_pending));
3939 else
3940 DEBUG(2,("Share del failed of %s\n",share_del_pending));
3941 share_del_pending[0] = 0;
3945 if (share_mode_pending) {
3946 unbecome_user();
3947 check_share_modes();
3948 share_mode_pending=False;
3951 errno = 0;
3953 for (counter=SMBD_SELECT_LOOP;
3954 !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
3955 counter += SMBD_SELECT_LOOP)
3957 int i;
3958 time_t t;
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()));
3965 return;
3968 t = time(NULL);
3970 /* become root again if waiting */
3971 unbecome_user();
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()));
3988 return;
3991 if (keepalive && (counter-last_keepalive)>keepalive) {
3992 if (!send_keepalive(Client)) {
3993 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3994 return;
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)
4005 dptr_idlecnum(i);
4007 if (Connections[i].num_files_open > 0 ||
4008 (t-Connections[i].lastused)<deadtime)
4009 allidle = False;
4012 if (allidle && num_connections_open>0) {
4013 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
4014 return;
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));
4026 nread = len + 4;
4028 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
4030 #ifdef WITH_VTP
4031 if(trans_num == 1 && VT_Check(InBuffer)) {
4032 VT_Process();
4033 return;
4035 #endif
4038 if (msg_type == 0)
4039 show_msg(InBuffer);
4041 nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
4043 if(nread > 0) {
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",
4050 nread,
4051 smb_len(OutBuffer)));
4053 else
4054 send_smb(Client,OutBuffer);
4056 trans_num++;
4061 /****************************************************************************
4062 initialise connect, service and file structs
4063 ****************************************************************************/
4064 static void init_structs(void )
4066 int i;
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,"");
4087 init_dptrs();
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");
4106 printf("\n");
4110 /****************************************************************************
4111 main program
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;
4118 int port = 139;
4119 int opt;
4120 extern char *optarg;
4122 #ifdef NEED_AUTH_PARAMETERS
4123 set_auth_parameters(argc,argv);
4124 #endif
4126 #ifdef SecureWare
4127 setluid(0);
4128 #endif
4130 append_log = True;
4132 TimeInit();
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 */
4142 #ifdef USE_SETRES
4143 setresuid(0,0,0);
4144 #else
4145 setuid(0);
4146 seteuid(0);
4147 setuid(0);
4148 seteuid(0);
4149 #endif
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)
4160 #ifdef HPUX
4161 setresgid(0,0,0);
4162 #else
4163 setgid(0);
4164 setegid(0);
4165 #endif
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] != '-'))
4175 argv++;
4176 argc--;
4179 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
4180 switch (opt)
4182 case 'O':
4183 strcpy(user_socket_options,optarg);
4184 break;
4185 case 'i':
4186 strcpy(scope,optarg);
4187 break;
4188 case 'P':
4190 extern BOOL passive;
4191 passive = True;
4193 break;
4194 case 's':
4195 strcpy(servicesf,optarg);
4196 break;
4197 case 'l':
4198 strcpy(debugf,optarg);
4199 break;
4200 case 'a':
4202 extern BOOL append_log;
4203 append_log = !append_log;
4205 break;
4206 case 'D':
4207 is_daemon = True;
4208 break;
4209 case 'd':
4210 if (*optarg == 'A')
4211 DEBUGLEVEL = 10000;
4212 else
4213 DEBUGLEVEL = atoi(optarg);
4214 break;
4215 case 'p':
4216 port = atoi(optarg);
4217 break;
4218 case 'h':
4219 usage(argv[0]);
4220 exit(0);
4221 break;
4222 default:
4223 usage(argv[0]);
4224 exit(1);
4227 reopen_logs();
4229 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4230 DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4232 GetWd(OriginalDir);
4234 #ifndef NO_GETRLIMIT
4235 #ifdef RLIMIT_NOFILE
4237 struct rlimit rlp;
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));
4244 #endif
4245 #endif
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"));
4254 exit(1);
4257 init_structs();
4259 if (!reload_services(False))
4260 return(-1);
4262 #ifndef NO_SIGNAL_TEST
4263 signal(SIGHUP,SIGNAL_CAST sig_hup);
4264 #endif
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"));
4271 is_daemon = True;
4274 if (is_daemon)
4276 DEBUG(3,("%s becoming a daemon\n",timestring()));
4277 become_daemon();
4280 if (open_sockets(is_daemon,port))
4282 /* possibly reload the services file. */
4283 reload_services(True);
4285 maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
4287 if (*lp_rootdir())
4289 if (sys_chroot(lp_rootdir()) == 0)
4290 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4293 process();
4294 close_sockets();
4296 exit_server("normal exit");
4297 return(0);