Initial version imported to CVS
[jra/samba/.git] / source3 / smbd / server.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Main SMB server routines
5    Copyright (C) Andrew Tridgell 1992-1995
6    
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.
11    
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.
16    
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.
20 */
21
22 #include "includes.h"
23 #include "loadparm.h"
24 #include "pcap.h"
25 #include "trans2.h"
26 #include "reply.h"
27
28 pstring servicesf = CONFIGFILE;
29 pstring OriginalDir ="/";
30 extern pstring debugf;
31 extern pstring sesssetup_user;
32
33 char *InBuffer = NULL;
34 char *OutBuffer = NULL;
35 char *last_inbuf = NULL;
36
37 int initial_uid = 0;
38 int initial_gid = 0;
39
40 BOOL share_mode_pending = False;
41
42 /* have I done a become_user? */
43 static struct {
44   int cnum, uid;
45 } last_user;
46
47 /* the last message the was processed */
48 int last_message = -1;
49
50 /* a useful macro to debug the last message processed */
51 #define LAST_MESSAGE() smb_fn_name(last_message)
52
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;
62
63 extern pstring user_socket_options;
64
65 connection_struct Connections[MAX_CONNECTIONS];
66 files_struct Files[MAX_OPEN_FILES];
67
68 extern int Protocol;
69
70 int maxxmit = BUFFER_SIZE;
71
72 int chain_size = 0;
73
74 /* a fnum to use when chaining */
75 int chain_fnum = -1;
76
77 /* number of open connections */
78 static int num_connections_open = 0;
79
80 extern fstring remote_machine;
81
82
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;
86
87
88 extern int extra_time_offset;
89
90 extern pstring myhostname;
91 extern struct in_addr myip;
92
93
94 static int find_free_connection(int hash);
95
96 #ifdef SMB_PASSWD
97 extern void generate_next_challenge(char *challenge);
98 extern void set_challenge(char *challenge);
99 #endif
100
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)
107
108
109
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)
122 {
123   mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
124
125   if ( !IS_DOS_READONLY(dosmode) )
126     result |= (S_IWUSR | S_IWGRP | S_IWOTH);
127  
128   if (IS_DOS_DIR(dosmode))
129     result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
130  
131   if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
132     result |= S_IXUSR;
133
134   if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
135     result |= S_IXGRP;
136  
137   if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
138     result |= S_IXOTH;  
139  
140   result &= CREATE_MODE(cnum);
141   return(result);
142 }
143
144
145 /****************************************************************************
146   change a unix mode to a dos mode
147 ****************************************************************************/
148 int dos_mode(int cnum,char *path,struct stat *sbuf)
149 {
150   int result = 0;
151
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;
174   }
175 #endif
176
177   if ((sbuf->st_mode & S_IXUSR) != 0)
178     result |= aARCH;
179
180   if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
181     result |= aSYSTEM;
182
183   if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
184     result |= aHIDDEN;   
185   
186   if (S_ISDIR(sbuf->st_mode))
187     result = aDIR | (result & aRONLY);
188
189 #if LINKS_READ_ONLY
190   if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
191     result |= aRONLY;
192 #endif
193
194   /* hide files with a name starting with a . */
195   if (lp_hide_dot_files(SNUM(cnum)))
196     {
197       char *p = strrchr(path,'/');
198       if (p)
199         p++;
200       else
201         p = path;
202       
203       if (p[0] == '.' && p[1] != '.' && p[1] != 0)
204         result |= aHIDDEN;
205     }
206
207   return(result);
208 }
209
210
211 /*******************************************************************
212 chmod a file - but preserve some bits
213 ********************************************************************/
214 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
215 {
216   struct stat st1;
217   int mask=0;
218   int tmp;
219   int unixmode;
220
221   if (!st) {
222     st = &st1;
223     if (sys_stat(fname,st)) return(-1);
224   }
225
226   if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
227
228   if (dos_mode(cnum,fname,st) == dosmode) return(0);
229
230   unixmode = unix_mode(cnum,dosmode);
231
232   /* preserve the s bits */
233   mask |= (S_ISUID | S_ISGID);
234
235   /* preserve the t bit */
236 #ifdef S_ISVTX
237   mask |= S_ISVTX;
238 #endif
239
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;
244
245   unixmode |= (st->st_mode & mask);
246
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;
251   }
252
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;
259   }
260     
261   return(chmod(fname,unixmode));
262 }
263
264
265 /****************************************************************************
266 check if two filenames are equal
267
268 this needs to be careful about whether we are case sensitive
269 ****************************************************************************/
270 static BOOL fname_equal(char *name1, char *name2)
271 {
272   int l1 = strlen(name1);
273   int l2 = strlen(name2);
274
275   /* handle filenames ending in a single dot */
276   if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
277     {
278       BOOL ret;
279       name1[l1-1] = 0;
280       ret = fname_equal(name1,name2);
281       name1[l1-1] = '.';
282       return(ret);
283     }
284
285   if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
286     {
287       BOOL ret;
288       name2[l2-1] = 0;
289       ret = fname_equal(name1,name2);
290       name2[l2-1] = '.';
291       return(ret);
292     }
293
294   /* now normal filename handling */
295   if (case_sensitive)
296     return(strcmp(name1,name2) == 0);
297
298   return(strequal(name1,name2));
299 }
300
301
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)
306 {
307   pstring tmpname;
308
309   if (is_8_3(name2))
310     return(False);
311
312   strcpy(tmpname,name2);
313   mangle_name_83(tmpname);
314
315   return(strequal(name1,tmpname));
316 }
317
318
319 /****************************************************************************
320 scan a directory to find a filename, matching without case sensitivity
321
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)
325 {
326   void *cur_dir;
327   char *dname;
328   BOOL mangled;
329   fstring name2;
330
331   mangled = is_mangled(name);
332
333   /* handle null paths */
334   if (*path == 0)
335     path = ".";
336
337   if (docache && (dname = DirCacheCheck(path,name,snum))) {
338     strcpy(name, dname);        
339     return(True);
340   }      
341
342   if (mangled)
343     check_mangled_stack(name);
344
345   /* open the directory */
346   if (!(cur_dir = OpenDir(path))) 
347     {
348       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
349       return(False);
350     }
351
352   /* now scan for matching names */
353   while ((dname = ReadDirName(cur_dir))) 
354     {
355       if (*dname == '.' &&
356           (strequal(dname,".") || strequal(dname,"..")))
357         continue;
358
359       strcpy(name2,dname);
360       if (!name_map_mangle(name2,False,snum)) continue;
361
362       if ((mangled && mangled_equal(name,name2))
363           || fname_equal(name, name2))
364         {
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);
370         }
371     }
372
373   CloseDir(cur_dir);
374   return(False);
375 }
376
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.
381
382 We assume that we have already done a chdir() to the right "root" directory
383 for this service.
384
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)
389 {
390   struct stat st;
391   char *start, *end;
392   pstring dirpath;
393
394   *dirpath = 0;
395
396   /* convert to basic unix format - removing \ chars and cleaning it up */
397   unix_format(name);
398   unix_clean_name(name);
399
400   if (!case_sensitive && 
401       (!case_preserve || (is_8_3(name) && !short_case_preserve)))
402     strnorm(name);
403
404   /* names must be relative to the root of the service - trim any leading /.
405    also trim trailing /'s */
406   trim_string(name,"/","/");
407
408   /* check if it's a printer file */
409   if (Connections[cnum].printer)
410     {
411       if ((! *name) || strchr(name,'/') || !is_8_3(name))
412         {
413           fstring name2;
414           sprintf(name2,"%.6s.XXXXXX",remote_machine);
415           strcpy(name,(char *)mktemp(name2));     
416         }      
417       return(True);
418     }
419
420   /* stat the name - if it exists then we are all done! */
421   if (sys_stat(name,&st) == 0)
422     return(True);
423
424   DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
425
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);
431
432   /* now we need to recursively match the name against the real 
433      directory structure */
434
435   start = name;
436   while (strncmp(start,"./",2) == 0)
437     start += 2;
438
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)) 
442     {
443       /* pinpoint the end of this section of the filename */
444       end = strchr(start, '/');
445
446       /* chop the name at this point */
447       if (end) *end = 0;
448
449       /* check if the name exists up to this point */
450       if (sys_stat(name, &st) == 0) 
451         {
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)) 
455             {
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);
460             }
461         }
462       else 
463         {
464           pstring rest;
465
466           *rest = 0;
467
468           /* remember the rest of the pathname so it can be restored
469              later */
470           if (end) strcpy(rest,end+1);
471
472
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))
476             {
477               if (end) 
478                 {
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);
483                 }
484               
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);
493
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);
498
499               DEBUG(5,("New file %s\n",start));
500               return(True); 
501             }
502
503           /* restore the rest of the string */
504           if (end) 
505             {
506               strcpy(start+strlen(start)+1,rest);
507               end = start + strlen(start);
508             }
509         }
510
511       /* add to the dirpath that we have resolved so far */
512       if (*dirpath) strcat(dirpath,"/");
513       strcat(dirpath,start);
514
515       /* restore the / that we wiped out earlier */
516       if (end) *end = '/';
517     }
518   
519   /* the name has been resolved */
520   DEBUG(5,("conversion finished %s\n",name));
521   return(True);
522 }
523
524
525
526
527 #ifdef QUOTAS
528 #ifdef LINUX
529 /****************************************************************************
530 try to get the disk space from disk quotas (LINUX version)
531 ****************************************************************************/
532 /*
533 If you didn't make the symlink to the quota package, too bad :(
534 */
535 #include "quota/quotactl.c"
536 #include "quota/hasquota.c"
537 static BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
538 {
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;
548   
549   /* find the block device file */
550   
551   if ( stat(path, &S) == -1 )
552     return(False) ;
553
554   devno = S.st_dev ;
555   
556   fp = setmntent(MOUNTED,"r");
557   found = False ;
558   
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 ;
565     }
566   }
567   endmntent(fp) ;
568   
569   if ( ! found )
570     return(False) ;
571   
572   qcmd = QCMD(Q_GETQUOTA, USRQUOTA);
573   
574   if (hasmntopt(mnt, MNTOPT_NOAUTO) || hasmntopt(mnt, MNTOPT_NOQUOTA))
575     return(False) ;
576   
577   if (!hasquota(mnt, USRQUOTA, &qfpathname))
578     return(False) ;
579   
580   euser_id = geteuid();
581   seteuid(0);
582   
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);
587     }
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);
599     }
600   }
601   seteuid(euser_id);
602   *bsize=1024;
603
604   if (D.dqb_bsoftlimit==0)
605     return(False);
606   if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curinodes>D.dqb_isoftlimit))
607     {
608       *dfree = 0;
609       *dsize = D.dqb_curblocks;
610     }
611   else {
612     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
613     *dsize = D.dqb_bsoftlimit;
614   }
615   return (True);
616 }
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)
623 {
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);
632
633   euser_id = geteuid();
634
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)
648     {
649       if (errno == EDQUOT) 
650         {
651           *dfree =0;
652           *dsize =D.dqb_curblocks;
653           return (True);
654         }
655       else return(False);
656     }
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)) 
659     {
660       *dfree = 0;
661       *dsize = D.dqb_curblocks;
662     }
663   else {
664     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
665     *dsize = D.dqb_bsoftlimit;
666   }
667   return (True);
668 }
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)
674 {
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 ;
685   
686   if ( stat(path,&sbuf) == -1 )
687     return(False) ;
688   
689   devno = sbuf.st_dev ;
690   
691   if ( devno != devno_cached ) {
692     
693     devno_cached = devno ;
694     
695     if ((fd = setmntent(KMTAB)) == NULL)
696       return(False) ;
697     
698     found = False ;
699     
700     while ((mnt = getmntent(fd)) != NULL) {
701       
702       if ( stat(mnt->mnt_dir,&sbuf) == -1 )
703         continue ;
704       
705       if (sbuf.st_dev == devno) {
706         
707         found = True ;
708         break ;
709         
710       }
711       
712     }
713     
714     strcpy(name,mnt->mnt_dir) ;
715     endmntent(fd) ;
716     
717     if ( ! found )
718       return(False) ;
719   }
720   
721   request.qf_magic = QF_MAGIC ;
722   request.qf_entry.id = geteuid() ;
723   
724   if (quotactl(name, Q_GETQUOTA, &request) == -1)
725     return(False) ;
726   
727   if ( ! request.user )
728     return(False) ;
729   
730   if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
731     
732     if ( ! quota_default ) {
733       
734       if ( quotactl(name, Q_GETHEADER, &header) == -1 )
735         return(False) ;
736       else
737         quota_default = header.user_h.def_fq ;
738     }
739     
740     *dfree = quota_default ;
741     
742   }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
743     
744     *dfree = 0 ;
745     
746   }else{
747     
748     *dfree = request.qf_entry.user_q.f_quota ;
749     
750   }
751   
752   *dsize = request.qf_entry.user_q.f_use ;
753   
754   if ( *dfree )
755     *dfree -= *dsize ;
756   
757   if ( *dfree < 0 )
758     *dfree = 0 ;
759   
760   *bsize = 4096 ;  /* Cray blocksize */
761   
762   return(True) ;
763   
764 }
765 #endif /* CRAY */
766 #endif /* LINUX */
767 #endif /* QUOTAS */
768
769
770 /****************************************************************************
771 normalise for DOS usage 
772 ****************************************************************************/
773 static void disk_norm(int *bsize,int *dfree,int *dsize)
774 {
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 */
784   }  
785
786   while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) 
787     {
788       *dfree /= 2;
789       *dsize /= 2;
790       *bsize *= 2;
791       if (*bsize > WORDMAX )
792         {
793           *bsize = WORDMAX;
794           if (*dsize > WORDMAX)
795             *dsize = WORDMAX;
796           if (*dfree >  WORDMAX)
797             *dfree = WORDMAX;
798           break;
799         }
800     }
801 }
802
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)
807 {
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
820
821 #ifdef QUOTAS
822   if (disk_quotas(path, bsize, dfree, dsize))
823     {
824       disk_norm(bsize,dfree,dsize);
825       return(((*bsize)/1024)*(*dfree));
826     }
827 #endif
828
829
830   /* possibly use system() to get the result */
831   if (df_command && *df_command)
832     {
833       int ret;
834       pstring syscmd;
835       pstring outfile;
836           
837       sprintf(outfile,"/tmp/dfree.smb.%d",(int)getpid());
838       sprintf(syscmd,"%s %s",df_command,path);
839       standard_sub_basic(syscmd);
840
841       ret = smbrun(syscmd,outfile);
842       DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
843           
844       {
845         FILE *f = fopen(outfile,"r");   
846         *dsize = 0;
847         *dfree = 0;
848         *bsize = 1024;
849         if (f)
850           {
851             fscanf(f,"%d %d %d",dsize,dfree,bsize);
852             fclose(f);
853           }
854         else
855           DEBUG(0,("Can't open %s\n",outfile));
856       }
857           
858       unlink(outfile);
859       disk_norm(bsize,dfree,dsize);
860       return(((*bsize)/1024)*(*dfree));
861     }
862
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 */
880           {
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));
886           }
887
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 */
904
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 */
912
913 #if defined(SCO) || defined(ISC) || defined(MIPS)
914   *bsize = 512;
915 #endif
916
917 /* handle rediculous bsize values - some OSes are broken */
918 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
919
920   disk_norm(bsize,dfree,dsize);
921
922   if (*bsize < 256)
923     *bsize = 512;
924   if ((*dsize)<1)
925     {
926       DEBUG(0,("dfree seems to be broken on your system\n"));
927       *dsize = 20*1024*1024/(*bsize);
928       *dfree = MAX(1,*dfree);
929     }
930   return(((*bsize)/1024)*(*dfree));
931 #endif
932 }
933
934
935 /****************************************************************************
936 wrap it to get filenames right
937 ****************************************************************************/
938 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
939 {
940   return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
941 }
942
943
944
945 /****************************************************************************
946 check a filename - possibly caling reducename
947
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)
953 {
954   BOOL ret;
955
956   errno = 0;
957
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));
961
962   return(ret);
963 }
964
965 /****************************************************************************
966 check a filename - possibly caling reducename
967 ****************************************************************************/
968 static void check_for_pipe(char *fname)
969 {
970   /* special case of pipe opens */
971   char s[10];
972   StrnCpy(s,fname,9);
973   strlower(s);
974   if (strstr(s,"pipe/"))
975     {
976       DEBUG(3,("Rejecting named pipe open for %s\n",fname));
977       unix_ERR_class = ERRSRV;
978       unix_ERR_code = ERRaccess;
979     }
980 }
981
982
983 /****************************************************************************
984 open a file
985 ****************************************************************************/
986 void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
987 {
988   pstring fname;
989
990   Files[fnum].open = False;
991   Files[fnum].fd = -1;
992   errno = EPERM;
993
994   strcpy(fname,fname1);
995
996   /* check permissions */
997   if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
998     {
999       DEBUG(3,("Permission denied opening %s\n",fname));
1000       check_for_pipe(fname);
1001       return;
1002     }
1003
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;
1008
1009 /*
1010   if (flags == O_WRONLY)
1011     DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
1012 */
1013
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
1020
1021
1022   Files[fnum].fd = sys_open(fname,flags,mode);
1023
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;
1039     }
1040   }
1041     
1042
1043   /* Fix for files ending in '.' */
1044   if((Files[fnum].fd == -1) && (errno == ENOENT) && 
1045      (strchr(fname,'.')==NULL))
1046     {
1047       strcat(fname,".");
1048       Files[fnum].fd = sys_open(fname,flags,mode);
1049     }
1050
1051 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
1052   if ((Files[fnum].fd == -1) && (errno == ENAMETOOLONG))
1053     {
1054       int max_len;
1055       char *p = strrchr(fname, '/');
1056
1057       if (p == fname)   /* name is "/xxx" */
1058         {
1059           max_len = pathconf("/", _PC_NAME_MAX);
1060           p++;
1061         }
1062       else if ((p == NULL) || (p == fname))
1063         {
1064           p = fname;
1065           max_len = pathconf(".", _PC_NAME_MAX);
1066         }
1067       else
1068         {
1069           *p = '\0';
1070           max_len = pathconf(fname, _PC_NAME_MAX);
1071           *p = '/';
1072           p++;
1073         }
1074       if (strlen(p) > max_len)
1075         {
1076           char tmp = p[max_len];
1077
1078           p[max_len] = '\0';
1079           if ((Files[fnum].fd = sys_open(fname,flags,mode)) == -1)
1080             p[max_len] = tmp;
1081         }
1082     }
1083 #endif
1084
1085   if (Files[fnum].fd < 0)
1086     {
1087       DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1088                fname,strerror(errno),flags));
1089       check_for_pipe(fname);
1090       return;
1091     }
1092
1093   if (Files[fnum].fd >= 0)
1094     {
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;      
1115
1116       /*
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
1122        */
1123       if (Files[fnum].print_file && POSTSCRIPT(cnum) && 
1124           Files[fnum].can_write) 
1125         {
1126           DEBUG(3,("Writing postscript line\n"));
1127           write_file(fnum,"%!\n",3);
1128         }
1129       
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));
1134
1135     }
1136
1137 #if USE_MMAP
1138   /* mmap it if read-only */
1139   if (!Files[fnum].can_write)
1140     {
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);
1144
1145       if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1146         {
1147           DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1148           Files[fnum].mmap_ptr = NULL;
1149         }
1150     }
1151 #endif
1152 }
1153
1154 /*******************************************************************
1155 sync a file
1156 ********************************************************************/
1157 void sync_file(int fnum)
1158 {
1159 #ifndef NO_FSYNC
1160   fsync(Files[fnum].fd);
1161 #endif
1162 }
1163
1164 /****************************************************************************
1165 run a file if it is a magic script
1166 ****************************************************************************/
1167 static void check_magic(int fnum,int cnum)
1168 {
1169   if (!*lp_magicscript(SNUM(cnum)))
1170     return;
1171
1172   DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1173
1174   {
1175     char *p;
1176     if (!(p = strrchr(Files[fnum].name,'/')))
1177       p = Files[fnum].name;
1178     else
1179       p++;
1180
1181     if (!strequal(lp_magicscript(SNUM(cnum)),p))
1182       return;
1183   }
1184
1185   {
1186     int ret;
1187     pstring magic_output;
1188     pstring fname;
1189     strcpy(fname,Files[fnum].name);
1190
1191     if (*lp_magicoutput(SNUM(cnum)))
1192       strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1193     else
1194       sprintf(magic_output,"%s.out",fname);
1195
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);
1200   }
1201 }
1202
1203
1204 /****************************************************************************
1205 close a file - possibly invalidating the read prediction
1206 ****************************************************************************/
1207 void close_file(int fnum)
1208 {
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) 
1214     {
1215       free((char *)Files[fnum].wbmpx_ptr);
1216       Files[fnum].wbmpx_ptr = NULL;
1217     }
1218
1219 #if USE_MMAP
1220   if(Files[fnum].mmap_ptr) 
1221     {
1222       munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
1223       Files[fnum].mmap_ptr = NULL;
1224     }
1225 #endif
1226
1227   if (lp_share_modes(SNUM(cnum)))
1228     del_share_mode(fnum);
1229
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);
1236       }
1237     }    
1238   }
1239
1240   close(Files[fnum].fd);
1241
1242   /* NT uses smbclose to start a print - weird */
1243   if (Files[fnum].print_file)
1244     print_file(fnum);
1245
1246   /* check for magic scripts */
1247   check_magic(fnum,cnum);
1248
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));
1252 }
1253
1254 enum {AFAIL,AREAD,AWRITE,AALL};
1255
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)
1261 {
1262   if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1263
1264   if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1265     if (old_deny == new_deny && share_pid == getpid()) 
1266         return(AALL);    
1267
1268     if (old_mode == 0) return(AREAD);
1269
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);
1280     }
1281
1282     return(AFAIL);
1283   }
1284
1285   switch (new_deny) 
1286     {
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);      
1302     }
1303   return(AFAIL);      
1304 }
1305
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)
1311 {
1312   int pid=0;
1313   int share_mode = get_share_mode_byname(cnum,fname,&pid);
1314
1315   if (!pid || !share_mode) return(True);
1316  
1317   if (share_mode == DENY_DOS)
1318     return(pid == getpid());
1319
1320   /* XXXX exactly what share mode combinations should be allowed for
1321      deleting/renaming? */
1322   return(False);
1323 }
1324
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)
1331 {
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;
1338     }
1339     else
1340       ftruncate(Files[fnum].fd,0); 
1341   }
1342 }
1343
1344
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)
1350 {
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;
1358
1359   Files[fnum].open = False;
1360   Files[fnum].fd = -1;
1361
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;
1367   }
1368
1369   if ((ofun & 0x3) == 0 && file_existed) {
1370     errno = EEXIST;
1371     return;
1372   }
1373       
1374   if (ofun & 0x10)
1375     flags2 |= O_CREAT;
1376   if ((ofun & 0x3) == 2)
1377     flags2 |= O_TRUNC;
1378
1379   /* note that we ignore the append flag as 
1380      append does not mean the same thing under dos and unix */
1381
1382   switch (share_mode&0xF)
1383     {
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;
1397     }
1398   
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;
1404     }
1405     flags = O_RDONLY;
1406   }
1407
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;
1412   }
1413
1414   if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1415
1416   if (lp_share_modes(SNUM(cnum))) {
1417     int old_share=0;
1418
1419     if (file_existed)
1420       old_share = get_share_mode(cnum,&sbuf,&share_pid);
1421
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;
1427
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;
1435       }
1436
1437       {
1438         int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1439                                           share_pid,fname);
1440
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;
1452         }
1453         
1454         if (access_allowed == AREAD)
1455           flags = O_RDONLY;
1456         
1457         if (access_allowed == AWRITE)
1458           flags = O_WRONLY;
1459       }
1460     }
1461   }
1462
1463   DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1464            flags,flags2,mode));
1465
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);
1470   }
1471
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;
1484     }
1485
1486     Files[fnum].share_mode = (deny_mode<<4) | open_mode;
1487     Files[fnum].share_pending = True;
1488
1489     if (Access) {
1490       (*Access) = open_mode;
1491     }
1492     
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;
1497     }
1498
1499     if (!share_pid)
1500       share_mode_pending = True;
1501
1502     if ((flags2&O_TRUNC) && file_existed)
1503       truncate_unless_locked(fnum,cnum);
1504   }
1505 }
1506
1507
1508
1509 /*******************************************************************
1510 check for files that we should now set our share modes on
1511 ********************************************************************/
1512 static void check_share_modes(void)
1513 {
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;
1523         }
1524       } else {
1525         Files[i].share_pending = False; 
1526       }
1527     }
1528 }
1529
1530
1531 /****************************************************************************
1532 seek a file. Try to avoid the seek if possible
1533 ****************************************************************************/
1534 int seek_file(int fnum,int pos)
1535 {
1536   int offset = 0;
1537   if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1538     offset = 3;
1539
1540   Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
1541   return(Files[fnum].pos);
1542 }
1543
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)
1548 {
1549   int ret=0;
1550
1551   if (!Files[fnum].can_write)
1552     {
1553       ret = read_predict(Files[fnum].fd,
1554                          pos,
1555                          data,
1556                          NULL,
1557                          maxcnt);
1558
1559       data += ret;
1560       maxcnt -= ret;
1561       mincnt = MAX(mincnt-ret,0);
1562       pos += ret;
1563     }
1564
1565 #if USE_MMAP
1566   if (Files[fnum].mmap_ptr)
1567     {
1568       int num = MIN(maxcnt,Files[fnum].mmap_size-pos);
1569       if (num > 0)
1570         {
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;
1577         }
1578     }
1579 #endif
1580
1581   if (maxcnt <= 0)
1582     return(ret);
1583
1584   if (seek_file(fnum,pos) != pos)
1585     {
1586       DEBUG(3,("Failed to seek to %d\n",pos));
1587       return(ret);
1588     }
1589   
1590   if (maxcnt > 0)
1591     ret += read_with_timeout(Files[fnum].fd,
1592                              data,
1593                              mincnt,
1594                              maxcnt,
1595                              timeout,
1596                              exact);
1597
1598   return(ret);
1599 }
1600
1601
1602 /****************************************************************************
1603 write to a file
1604 ****************************************************************************/
1605 int write_file(int fnum,char *data,int n)
1606 {
1607   if (!Files[fnum].can_write) {
1608     errno = EPERM;
1609     return(0);
1610   }
1611
1612   Files[fnum].modified = True;
1613
1614   return(write_data(Files[fnum].fd,data,n));
1615 }
1616
1617
1618 static int old_umask = 022;
1619
1620 /****************************************************************************
1621 load parameters specific to a connection/service
1622 ****************************************************************************/
1623 BOOL become_service(int cnum,BOOL do_chdir)
1624 {
1625   extern char magic_char;
1626   static int last_cnum = -1;
1627   int snum;
1628
1629   if (!OPEN_CNUM(cnum))
1630     {
1631       last_cnum = -1;
1632       return(False);
1633     }
1634
1635   Connections[cnum].lastused = smb_last_time;
1636
1637   snum = SNUM(cnum);
1638   
1639   if (do_chdir &&
1640       ChDir(Connections[cnum].connectpath) != 0 &&
1641       ChDir(Connections[cnum].origpath) != 0)
1642     {
1643       DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1644             Connections[cnum].connectpath,cnum));     
1645       return(False);
1646     }
1647
1648   if (cnum == last_cnum)
1649     return(True);
1650
1651   last_cnum = cnum;
1652
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);
1661 }
1662
1663
1664 /****************************************************************************
1665   become the specified uid 
1666 ****************************************************************************/
1667 static BOOL become_uid(int uid)
1668 {
1669   if (initial_uid != 0)
1670     return(True);
1671
1672 #ifdef AIX
1673   {
1674     /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */
1675     priv_t priv;
1676
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)"));
1684   }
1685 #endif
1686
1687 #ifdef USE_SETRES
1688   if (setresuid(-1,uid,-1) != 0)
1689 #else
1690     if ((seteuid(uid) != 0) && 
1691         (setuid(uid) != 0))
1692 #endif
1693       {
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);
1699       }
1700
1701   if (((uid == -1) || (uid == 65535)) && geteuid() != uid)
1702     {
1703       DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n"));
1704       return(False);
1705     }
1706
1707   return(True);
1708 }
1709
1710
1711 /****************************************************************************
1712   become the specified gid
1713 ****************************************************************************/
1714 static BOOL become_gid(int gid)
1715 {
1716   if (initial_uid != 0)
1717     return(True);
1718   
1719 #ifdef USE_SETRES 
1720   if (setresgid(-1,gid,-1) != 0)
1721 #else
1722     if (setgid(gid) != 0)
1723 #endif
1724       {
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);
1730       }
1731
1732   return(True);
1733 }
1734
1735
1736 /****************************************************************************
1737   become the specified uid and gid
1738 ****************************************************************************/
1739 static BOOL become_id(int uid,int gid)
1740 {
1741   return(become_gid(gid) && become_uid(uid));
1742 }
1743
1744 /****************************************************************************
1745 become the guest user
1746 ****************************************************************************/
1747 static BOOL become_guest(void)
1748 {
1749   BOOL ret;
1750   static struct passwd *pass=NULL;
1751
1752   if (initial_uid != 0) 
1753     return(True);
1754
1755   if (!pass)
1756     pass = Get_Pwnam(lp_guestaccount(-1),True);
1757   if (!pass) return(False);
1758
1759   ret = become_id(pass->pw_uid,pass->pw_gid);
1760
1761   if (!ret)
1762     DEBUG(1,("Failed to become guest. Invalid guest account?\n"));
1763
1764   last_user.cnum = -2;
1765
1766   return(ret);
1767 }
1768
1769 /*******************************************************************
1770 check if a username is OK
1771 ********************************************************************/
1772 static BOOL check_user_ok(int cnum,user_struct *vuser,int snum)
1773 {
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);
1777
1778   if (!user_ok(vuser->name,snum)) return(False);
1779
1780   i = Connections[cnum].uid_cache.entries % UID_CACHE_SIZE;
1781   Connections[cnum].uid_cache.list[i] = vuser->uid;
1782
1783   if (Connections[cnum].uid_cache.entries < UID_CACHE_SIZE)
1784     Connections[cnum].uid_cache.entries++;
1785
1786   return(True);
1787 }
1788
1789
1790 /****************************************************************************
1791   become the user of a connection number
1792 ****************************************************************************/
1793 BOOL become_user(int cnum, int uid)
1794 {
1795   int new_umask;
1796   user_struct *vuser;
1797   int snum,gid;
1798   int ngroups;
1799   gid_t *groups;
1800
1801   if (last_user.cnum == cnum && last_user.uid == uid) {
1802     DEBUG(4,("Skipping become_user - already user\n"));
1803     return(True);
1804   }
1805
1806   unbecome_user();
1807
1808   if (!OPEN_CNUM(cnum)) {
1809     DEBUG(2,("Connection %d not open\n",cnum));
1810     return(False);
1811   }
1812
1813   snum = Connections[cnum].service;
1814
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);
1827     }
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;
1835   }
1836
1837   if (initial_uid == 0)
1838     {
1839       if (!become_gid(gid)) return(False);
1840
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"));
1847       }
1848 #endif
1849
1850       if (!Connections[cnum].admin_user && !become_uid(uid))
1851         return(False);
1852     }
1853
1854   new_umask = 0777 & ~CREATE_MODE(cnum);
1855   old_umask = umask(new_umask);
1856
1857   last_user.cnum = cnum;
1858   last_user.uid = uid;
1859   
1860   DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d) new_umask=0%o\n",
1861            getuid(),geteuid(),getgid(),getegid(),new_umask));
1862   
1863   return(True);
1864 }
1865
1866 /****************************************************************************
1867   unbecome the user of a connection number
1868 ****************************************************************************/
1869 BOOL unbecome_user(void )
1870 {
1871   if (last_user.cnum == -1)
1872     return(False);
1873
1874   ChDir(OriginalDir);
1875
1876   umask(old_umask);
1877
1878   if (initial_uid == 0)
1879     {
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
1888     }
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)
1896     {
1897       DEBUG(0,("Warning: You appear to have a trapdoor uid system\n"));
1898       initial_uid = geteuid();
1899     }
1900   if (getegid() != initial_gid)
1901     {
1902       DEBUG(0,("Warning: You appear to have a trapdoor gid system\n"));
1903       initial_gid = getegid();
1904     }
1905 #endif
1906   
1907   if (ChDir(OriginalDir) != 0)
1908     DEBUG(0,("%s chdir(%s) failed in unbecome_user\n",
1909              timestring(),OriginalDir));  
1910
1911   DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
1912         getuid(),geteuid(),getgid(),getegid()));
1913
1914   last_user.cnum = -1;
1915
1916   return(True);
1917 }
1918
1919 /****************************************************************************
1920   find a service entry
1921 ****************************************************************************/
1922 int find_service(char *service)
1923 {
1924    int iService;
1925
1926    string_sub(service,"\\","/");
1927
1928    iService = lp_servicenumber(service);
1929
1930    /* now handle the special case of a home directory */
1931    if (iService < 0)
1932    {
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)
1937       {   
1938          int iHomeService;
1939          if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1940          {
1941             lp_add_home(service,iHomeService,phome_dir);
1942             iService = lp_servicenumber(service);
1943          }
1944       }
1945    }
1946
1947    /* If we still don't have a service, attempt to add it as a printer. */
1948    if (iService < 0)
1949    {
1950       int iPrinterService;
1951
1952       if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1953       {
1954          char *pszTemp;
1955
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))
1959          {
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));
1966          }
1967          else
1968             DEBUG(3,("%s is not a valid printer name\n", service));
1969       }
1970    }
1971
1972    /* just possibly it's a default service? */
1973    if (iService < 0) 
1974      {
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);
1981          }
1982        }
1983      }
1984
1985    if (iService >= 0)
1986       if (!VALID_SNUM(iService))
1987       {
1988          DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1989          iService = -1;
1990       }
1991
1992    if (iService < 0)
1993       DEBUG(3,("find_service() failed to find service %s\n", service));
1994
1995    return (iService);
1996 }
1997
1998
1999 /****************************************************************************
2000   create an error packet from a cached error.
2001 ****************************************************************************/
2002 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
2003 {
2004   write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
2005
2006   int32 eclass = wbmpx->wr_errclass;
2007   int32 err = wbmpx->wr_error;
2008
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);
2013 }
2014
2015
2016 struct
2017 {
2018   int unixerror;
2019   int smbclass;
2020   int smbcode;
2021 } unix_smb_errmap[] =
2022 {
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}
2044 };
2045
2046
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)
2051 {
2052   int eclass=def_class;
2053   int ecode=def_code;
2054   int i=0;
2055
2056   if (unix_ERR_class != SUCCESS)
2057     {
2058       eclass = unix_ERR_class;
2059       ecode = unix_ERR_code;
2060       unix_ERR_class = SUCCESS;
2061       unix_ERR_code = 0;
2062     }
2063   else
2064     {
2065       while (unix_smb_errmap[i].smbclass != 0)
2066         {
2067           if (unix_smb_errmap[i].unixerror == errno)
2068             {
2069               eclass = unix_smb_errmap[i].smbclass;
2070               ecode = unix_smb_errmap[i].smbcode;
2071               break;
2072             }
2073           i++;
2074         }
2075     }
2076
2077   return(error_packet(inbuf,outbuf,eclass,ecode,line));
2078 }
2079
2080
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)
2085 {
2086   int outsize = set_message(outbuf,0,0,True);
2087   int cmd;
2088   cmd = CVAL(inbuf,smb_com);
2089   
2090   CVAL(outbuf,smb_rcls) = error_class;
2091   SSVAL(outbuf,smb_err,error_code);  
2092   
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));
2100
2101   if (errno != 0)
2102     DEBUG(3,("error string = %s\n",strerror(errno)));
2103   
2104   return(outsize);
2105 }
2106
2107
2108 #ifndef SIGCLD_IGNORE
2109 /****************************************************************************
2110 this prevents zombie child processes
2111 ****************************************************************************/
2112 static int sig_cld()
2113 {
2114   static int depth = 0;
2115   if (depth != 0)
2116     {
2117       DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2118       depth=0;
2119       return(0);
2120     }
2121   depth++;
2122
2123   BlockSignals(True);
2124   DEBUG(5,("got SIGCLD\n"));
2125
2126 #ifdef USE_WAITPID
2127   while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2128 #endif
2129
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. */
2136         
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
2144
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;
2151 }
2152 #endif
2153
2154 /****************************************************************************
2155   this is called when the client exits abruptly
2156   **************************************************************************/
2157 static int sig_pipe()
2158 {
2159   exit_server("Got sigpipe\n");
2160   return(0);
2161 }
2162
2163 /****************************************************************************
2164   open the socket communication
2165 ****************************************************************************/
2166 static BOOL open_sockets(BOOL is_daemon,int port)
2167 {
2168   extern int Client;
2169
2170   if (is_daemon)
2171     {
2172       int s;
2173       struct sockaddr addr;
2174       int in_addrlen = sizeof(addr);
2175        
2176       /* Stop zombies */
2177 #ifdef SIGCLD_IGNORE
2178       signal(SIGCLD, SIG_IGN);
2179 #else
2180       signal(SIGCLD, SIGNAL_CAST sig_cld);
2181 #endif
2182
2183       /* open an incoming socket */
2184       s = open_socket_in(SOCK_STREAM, port, 0);
2185       if (s == -1)
2186         return(False);
2187
2188       /* ready to listen */
2189       if (listen(s, 5) == -1) 
2190         {
2191           DEBUG(0,("listen: %s",strerror(errno)));
2192           close(s);
2193           return False;
2194         }
2195       
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)
2200         {
2201           Client = accept(s,&addr,&in_addrlen);
2202
2203           if (Client == -1 && errno == EINTR)
2204             continue;
2205
2206           if (Client == -1)
2207             {
2208               DEBUG(0,("accept: %s",strerror(errno)));
2209               return False;
2210             }
2211
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)
2220             {
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();
2227   
2228               set_socket_options(Client,"SO_KEEPALIVE");
2229               set_socket_options(Client,user_socket_options);
2230
2231               return True; 
2232             }
2233           close(Client); /* The parent doesn't need this socket */
2234 #endif
2235         }
2236     }
2237   else
2238     {
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);
2245
2246       /* close our standard file descriptors */
2247       close_low_fds();
2248
2249       set_socket_options(Client,"SO_KEEPALIVE");
2250       set_socket_options(Client,user_socket_options);
2251     }
2252
2253   return True;
2254 }
2255
2256
2257 /****************************************************************************
2258 check if a snum is in use
2259 ****************************************************************************/
2260 BOOL snum_used(int snum)
2261 {
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);
2267 }
2268
2269 /****************************************************************************
2270   reload the services file
2271   **************************************************************************/
2272 BOOL reload_services(BOOL test)
2273 {
2274   BOOL ret;
2275
2276   if (lp_loaded())
2277     {
2278       pstring fname;
2279       strcpy(fname,lp_configfile());
2280       if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2281         {
2282           strcpy(servicesf,fname);
2283           test = False;
2284         }
2285     }
2286
2287   reopen_logs();
2288
2289   if (test && !lp_file_list_changed())
2290     return(True);
2291
2292   lp_killunused(snum_used);
2293
2294   ret = lp_load(servicesf,False);
2295
2296   /* perhaps the config filename is now set */
2297   if (!test)
2298     reload_services(True);
2299
2300   reopen_logs();
2301
2302   {
2303     extern int Client;
2304     if (Client != -1) {      
2305       set_socket_options(Client,"SO_KEEPALIVE");
2306       set_socket_options(Client,user_socket_options);
2307     }
2308   }
2309
2310   create_mangled_stack(lp_mangledstack());
2311
2312   /* this forces service parameters to be flushed */
2313   become_service(-1,True);
2314
2315   return(ret);
2316 }
2317
2318
2319
2320 /****************************************************************************
2321 this prevents zombie child processes
2322 ****************************************************************************/
2323 static int sig_hup()
2324 {
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);
2333 }
2334
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)
2340 {
2341   if (-1 == initgroups(user,gid))
2342     {
2343       if (getuid() == 0)
2344         {
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));
2348         }
2349     }
2350   else
2351     {
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);
2362
2363       if (igroups[0] == 0x42424242)
2364         ngroups = 0;
2365
2366       *p_ngroups = ngroups;
2367
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)
2374         {
2375           /* does getgroups return ints or gid_t ?? */
2376           static BOOL groups_use_ints = True;
2377
2378           if (groups_use_ints && 
2379               ngroups == 1 && 
2380               SVAL(igroups,2) == 0x4242)
2381             groups_use_ints = False;
2382           
2383           for (i=0;groups_use_ints && i<ngroups;i++)
2384             if (igroups[i] == 0x42424242)
2385               groups_use_ints = False;
2386               
2387           if (groups_use_ints)
2388             {
2389               *p_igroups = igroups;
2390               *p_groups = (gid_t *)igroups;       
2391             }
2392           else
2393             {
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;
2400             }
2401         }
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"));
2406     }
2407   return 0;
2408 }
2409
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)
2414 {
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;
2422
2423   strlower(service);
2424
2425   snum = find_service(service);
2426   if (snum < 0)
2427     {
2428       if (strequal(service,"IPC$"))
2429         {         
2430           DEBUG(3,("%s refusing IPC connection\n",timestring()));
2431           return(-3);
2432         }
2433
2434       DEBUG(0,("%s couldn't find service %s\n",timestring(),service));      
2435       return(-2);
2436     }
2437
2438   if (strequal(service,HOMES_NAME))
2439     {
2440       if (*user && Get_Pwnam(user,True))
2441         return(make_connection(user,user,password,pwlen,dev,vuid));
2442
2443       if (validated_username(vuid))
2444         {
2445           strcpy(user,validated_username(vuid));
2446           return(make_connection(user,user,password,pwlen,dev,vuid));
2447         }
2448     }
2449
2450   if (!lp_snum_ok(snum) || !check_access(snum)) {    
2451     return(-4);
2452   }
2453
2454   /* you can only connect to the IPC$ service as an ipc device */
2455   if (strequal(service,"IPC$"))
2456     strcpy(dev,"IPC");
2457
2458   if (*dev == '?' || !*dev)
2459     {
2460       if (lp_print_ok(snum))
2461         strcpy(dev,"LPT1:");
2462       else
2463         strcpy(dev,"A:");
2464     }
2465
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);
2471   }
2472
2473   /* lowercase the user name */
2474   strlower(user);
2475
2476   /* add it as a possible user name */
2477   add_session_user(service);
2478
2479   /* shall we let them in? */
2480   if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2481     {
2482       DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2483       return(-1);
2484     }
2485   
2486   cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2487   if (cnum < 0)
2488     {
2489       DEBUG(0,("%s couldn't find free connection\n",timestring()));      
2490       return(-1);
2491     }
2492
2493   pcon = &Connections[cnum];
2494   bzero((char *)pcon,sizeof(*pcon));
2495
2496   /* find out some info about the user */
2497   pass = Get_Pwnam(user,True);
2498
2499   if (pass == NULL)
2500     {
2501       DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); 
2502       return(-7);
2503     }
2504
2505   pcon->read_only = lp_readonly(snum);
2506
2507   {
2508     pstring list;
2509     StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2510     string_sub(list,"%S",service);
2511
2512     if (user_in_list(user,list))
2513       pcon->read_only = True;
2514
2515     StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2516     string_sub(list,"%S",service);
2517
2518     if (user_in_list(user,list))
2519       pcon->read_only = False;    
2520   }
2521
2522   /* admin user check */
2523   if (user_in_list(user,lp_admin_users(snum)) &&
2524       !pcon->read_only)
2525     {
2526       pcon->admin_user = True;
2527       DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2528     }
2529   else
2530     pcon->admin_user = False;
2531     
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);
2544
2545 #if HAVE_GETGRNAM 
2546   if (*lp_force_group(snum))
2547     {
2548       struct group *gptr = (struct group *)getgrnam(lp_force_group(snum));
2549       if (gptr)
2550         {
2551           pcon->gid = gptr->gr_gid;
2552           DEBUG(3,("Forced group %s\n",lp_force_group(snum)));
2553         }
2554       else
2555         DEBUG(1,("Couldn't find group %s\n",lp_force_group(snum)));
2556     }
2557 #endif
2558
2559   if (*lp_force_user(snum))
2560     {
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)
2566         {
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));    
2572         }
2573       else
2574         DEBUG(1,("Couldn't find user %s\n",fuser));
2575     }
2576
2577   {
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));
2583   }
2584
2585   /* groups stuff added by ih */
2586   pcon->ngroups = 0;
2587   pcon->groups = NULL;
2588
2589   if (!IS_IPC(cnum))
2590     {
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);
2593       
2594       /* check number of connections */
2595       if (!claim_connection(cnum,
2596                             lp_servicename(SNUM(cnum)),
2597                             lp_max_connections(SNUM(cnum)),False))
2598         {
2599           DEBUG(1,("too many connections - rejected\n"));
2600           return(-8);
2601         }  
2602
2603       if (lp_status(SNUM(cnum)))
2604         claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2605
2606       first_connection = False;
2607     } /* IS_IPC */
2608
2609   pcon->open = True;
2610
2611   /* execute any "root preexec = " line */
2612   if (*lp_rootpreexec(SNUM(cnum)))
2613     {
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);
2619     }
2620
2621   if (!become_user(cnum,pcon->uid))
2622     {
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);
2630       }
2631       return(-1);
2632     }
2633
2634   if (ChDir(pcon->connectpath) != 0)
2635     {
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);
2644       }
2645       return(-5);      
2646     }
2647
2648   string_set(&pcon->origpath,pcon->connectpath);
2649
2650 #if SOFTLINK_OPTIMISATION
2651   /* resolve any soft links early */
2652   {
2653     pstring s;
2654     strcpy(s,pcon->connectpath);
2655     GetWd(s);
2656     string_set(&pcon->connectpath,s);
2657     ChDir(pcon->connectpath);
2658   }
2659 #endif
2660
2661   num_connections_open++;
2662   add_session_user(user);
2663   
2664   /* execute any "preexec = " line */
2665   if (*lp_preexec(SNUM(cnum)))
2666     {
2667       pstring cmd;
2668       strcpy(cmd,lp_preexec(SNUM(cnum)));
2669       standard_sub(cnum,cmd);
2670       smbrun(cmd,NULL);
2671     }
2672   
2673   /* we've finished with the sensitive stuff */
2674   unbecome_user();
2675
2676   {
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()));
2685   }
2686
2687   return(cnum);
2688 }
2689
2690
2691 /****************************************************************************
2692   find first available file slot
2693 ****************************************************************************/
2694 int find_free_file(void )
2695 {
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);
2702 }
2703
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 )
2710 {
2711   int i;
2712   BOOL used=False;
2713   hash = (hash % (MAX_CONNECTIONS-2))+1;
2714
2715  again:
2716
2717   for (i=hash+1;i!=hash;)
2718     {
2719       if (!Connections[i].open && Connections[i].used == used) 
2720         {
2721           DEBUG(3,("found free connection number %d\n",i));
2722           return(i);
2723         }
2724       i++;
2725       if (i == MAX_CONNECTIONS)
2726         i = 1;
2727     }
2728
2729   if (!used)
2730     {
2731       used = !used;
2732       goto again;
2733     }
2734
2735   DEBUG(1,("ERROR! Out of connection structures\n"));
2736   return(-1);
2737 }
2738
2739
2740 /****************************************************************************
2741 reply for the core protocol
2742 ****************************************************************************/
2743 int reply_corep(char *outbuf)
2744 {
2745   int outsize = set_message(outbuf,1,0,True);
2746
2747   Protocol = PROTOCOL_CORE;
2748
2749   return outsize;
2750 }
2751
2752
2753 /****************************************************************************
2754 reply for the coreplus protocol
2755 ****************************************************************************/
2756 int reply_coreplus(char *outbuf)
2757 {
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 */  
2764
2765   Protocol = PROTOCOL_COREPLUS;
2766
2767   return outsize;
2768 }
2769
2770
2771 /****************************************************************************
2772 reply for the lanman 1.0 protocol
2773 ****************************************************************************/
2774 int reply_lanman1(char *outbuf)
2775 {
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);
2780
2781   if (lp_security()>=SEC_USER) secword |= 1;
2782   if (doencrypt) secword |= 2;
2783
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
2791
2792   Protocol = PROTOCOL_LANMAN1;
2793
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
2799   }
2800
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);
2809
2810   put_dos_date(outbuf,smb_vwv8,t);
2811
2812   return (smb_len(outbuf)+4);
2813 }
2814
2815
2816 /****************************************************************************
2817 reply for the lanman 2.0 protocol
2818 ****************************************************************************/
2819 int reply_lanman2(char *outbuf)
2820 {
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);
2825
2826   if (lp_security()>=SEC_USER) secword |= 1;
2827   if (doencrypt) secword |= 2;
2828
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
2836
2837   SIVAL(outbuf,smb_vwv6,getpid());
2838
2839   Protocol = PROTOCOL_LANMAN2;
2840
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
2846   }
2847
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);
2855
2856   return (smb_len(outbuf)+4);
2857 }
2858
2859 /****************************************************************************
2860 reply for the nt protocol
2861 ****************************************************************************/
2862 int reply_nt1(char *outbuf)
2863 {
2864   int capabilities=0x300; /* has dual names + lock_and_read */
2865   int secword=0;
2866   BOOL doencrypt = SMBENCRYPT();
2867
2868   if (lp_security()>=SEC_USER) secword |= 1;
2869   if (doencrypt) secword |= 2;
2870
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);
2879   }
2880 #endif
2881
2882   SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2883
2884   Protocol = PROTOCOL_NT1;
2885
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
2891   }
2892
2893   if (lp_readraw() && lp_writeraw())
2894     capabilities |= 1;
2895
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);
2903
2904   return (smb_len(outbuf)+4);
2905 }
2906
2907
2908 /* these are the protocol lists used for auto architecture detection:
2909
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]
2919
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]
2929
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]
2936 */
2937
2938 /*
2939   * Modified to recognize the architecture of the remote machine better.
2940   *
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
2955   *
2956   *  tim@fsg.com 09/29/95
2957   */
2958   
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
2964  
2965 #define ARCH_ALL      0x1F
2966  
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},
2984 };
2985
2986
2987 /****************************************************************************
2988   reply to a negprot
2989 ****************************************************************************/
2990 static int reply_negprot(char *inbuf,char *outbuf)
2991 {
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;
3000
3001   p = smb_buf(inbuf)+1;
3002   while (p < (smb_buf(inbuf) + bcc))
3003     { 
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;
3025       }
3026  
3027       p += strlen(p) + 2;
3028     }
3029     
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;
3049   }
3050  
3051   /* possibly reload - change of architecture */
3052   reload_services(True);      
3053     
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!");
3058   
3059   /* Check for protocols, most desirable first */
3060   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
3061     {
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))
3066           { 
3067             if (strequal(p,supported_protocols[protocol].proto_name))
3068               choice = Index;
3069             Index++;
3070             p += strlen(p) + 2;
3071           }
3072       if(choice != -1)
3073         break;
3074     }
3075   
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));
3083   }
3084   else {
3085     DEBUG(0,("No protocol supported !\n"));
3086   }
3087   SSVAL(outbuf,smb_vwv0,choice);
3088   
3089   DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3090
3091   return(outsize);
3092 }
3093
3094
3095 /****************************************************************************
3096   parse a connect packet
3097 ****************************************************************************/
3098 void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev)
3099 {
3100   char *p = smb_buf(buf) + 1;
3101   char *p2;
3102
3103   DEBUG(4,("parsing connect string %s\n",p));
3104     
3105   p2 = strrchr(p,'\\');
3106   if (p2 == NULL)
3107     strcpy(service,p);
3108   else
3109     strcpy(service,p2+1);
3110   
3111   p += strlen(p) + 2;
3112   
3113   strcpy(password,p);
3114   *pwlen = strlen(password);
3115
3116   p += strlen(p) + 2;
3117
3118   strcpy(dev,p);
3119   
3120   *user = 0;
3121   p = strchr(service,'%');
3122   if (p != NULL)
3123     {
3124       *p = 0;
3125       strcpy(user,p+1);
3126     }
3127 }
3128
3129
3130 /****************************************************************************
3131 close all open files for a connection
3132 ****************************************************************************/
3133 static void close_open_files(int cnum)
3134 {
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);
3139     }
3140 }
3141
3142
3143
3144 /****************************************************************************
3145 close a cnum
3146 ****************************************************************************/
3147 void close_cnum(int cnum, int uid)
3148 {
3149   extern struct from_host Client_info;
3150
3151   DirCacheFlush(SNUM(cnum));
3152
3153   unbecome_user();
3154
3155   if (!OPEN_CNUM(cnum))
3156     {
3157       DEBUG(0,("Can't close cnum %d\n",cnum));
3158       return;
3159     }
3160
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))));
3165
3166   yield_connection(cnum,
3167                    lp_servicename(SNUM(cnum)),
3168                    lp_max_connections(SNUM(cnum)));
3169
3170   if (lp_status(SNUM(cnum)))
3171     yield_connection(cnum,"STATUS.",MAXSTATUS);
3172
3173   close_open_files(cnum);
3174   dptr_closecnum(cnum);
3175
3176   /* execute any "postexec = " line */
3177   if (*lp_postexec(SNUM(cnum)) && become_user(cnum,uid))
3178     {
3179       pstring cmd;
3180       strcpy(cmd,lp_postexec(SNUM(cnum)));
3181       standard_sub(cnum,cmd);
3182       smbrun(cmd,NULL);
3183       unbecome_user();
3184     }
3185
3186   unbecome_user();
3187   /* execute any "root postexec = " line */
3188   if (*lp_rootpostexec(SNUM(cnum)))
3189     {
3190       pstring cmd;
3191       strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3192       standard_sub(cnum,cmd);
3193       smbrun(cmd,NULL);
3194     }
3195
3196   Connections[cnum].open = False;
3197   num_connections_open--;
3198   if (Connections[cnum].ngroups && Connections[cnum].groups)
3199     {
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;
3206     }
3207
3208   string_set(&Connections[cnum].user,"");
3209   string_set(&Connections[cnum].dirpath,"");
3210   string_set(&Connections[cnum].connectpath,"");
3211 }
3212
3213
3214 /****************************************************************************
3215 simple routines to do connection counting
3216 ****************************************************************************/
3217 BOOL yield_connection(int cnum,char *name,int max_connections)
3218 {
3219   struct connect_record crec;
3220   pstring fname;
3221   FILE *f;
3222   int mypid = getpid();
3223   int i;
3224
3225   DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3226
3227   if (max_connections <= 0)
3228     return(True);
3229
3230   bzero(&crec,sizeof(crec));
3231
3232   strcpy(fname,lp_lockdir());
3233   standard_sub(cnum,fname);
3234   trim_string(fname,"","/");
3235
3236   strcat(fname,"/");
3237   strcat(fname,name);
3238   strcat(fname,".LCK");
3239
3240   f = fopen(fname,"r+");
3241   if (!f)
3242     {
3243       DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
3244       return(False);
3245     }
3246
3247   fseek(f,0,SEEK_SET);
3248
3249   /* find a free spot */
3250   for (i=0;i<max_connections;i++)
3251     {
3252       if (fread(&crec,sizeof(crec),1,f) != 1)
3253         {
3254           DEBUG(2,("Entry not found in lock file %s\n",fname));
3255           fclose(f);
3256           return(False);
3257         }
3258       if (crec.pid == mypid && crec.cnum == cnum)
3259         break;
3260     }
3261
3262   if (crec.pid != mypid || crec.cnum != cnum)
3263     {
3264       fclose(f);
3265       DEBUG(2,("Entry not found in lock file %s\n",fname));
3266       return(False);
3267     }
3268
3269   bzero((void *)&crec,sizeof(crec));
3270   
3271   /* remove our mark */
3272   if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3273       fwrite(&crec,sizeof(crec),1,f) != 1)
3274     {
3275       DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3276       fclose(f);
3277       return(False);
3278     }
3279
3280   DEBUG(3,("Yield successful\n"));
3281
3282   fclose(f);
3283   return(True);
3284 }
3285
3286
3287 /****************************************************************************
3288 simple routines to do connection counting
3289 ****************************************************************************/
3290 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3291 {
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;
3298
3299   if (max_connections <= 0)
3300     return(True);
3301
3302   DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3303
3304   strcpy(fname,lp_lockdir());
3305   standard_sub(cnum,fname);
3306   trim_string(fname,"","/");
3307
3308   if (!directory_exist(fname,NULL))
3309     mkdir(fname,0755);
3310
3311   strcat(fname,"/");
3312   strcat(fname,name);
3313   strcat(fname,".LCK");
3314
3315   if (!file_exist(fname,NULL))
3316     {
3317       f = fopen(fname,"w");
3318       if (f) fclose(f);
3319     }
3320
3321   total_recs = file_size(fname) / sizeof(crec);
3322
3323   f = fopen(fname,"r+");
3324
3325   if (!f)
3326     {
3327       DEBUG(1,("couldn't open lock file %s\n",fname));
3328       return(False);
3329     }
3330
3331   /* find a free spot */
3332   for (i=0;i<max_connections;i++)
3333     {
3334
3335       if (i>=total_recs || 
3336           fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3337           fread(&crec,sizeof(crec),1,f) != 1)
3338         {
3339           if (foundi < 0) foundi = i;
3340           break;
3341         }
3342
3343       if (Clear && crec.pid && !process_exists(crec.pid))
3344         {
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;
3350         }
3351       if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3352         {
3353           foundi=i;
3354           if (!Clear) break;
3355         }
3356     }  
3357
3358   if (foundi < 0)
3359     {
3360       DEBUG(3,("no free locks in %s\n",fname));
3361       fclose(f);
3362       return(False);
3363     }      
3364
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);
3374
3375   {
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);
3379   }
3380   
3381   /* make our mark */
3382   if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3383       fwrite(&crec,sizeof(crec),1,f) != 1)
3384     {
3385       fclose(f);
3386       return(False);
3387     }
3388
3389   fclose(f);
3390   return(True);
3391 }
3392
3393 #if DUMP_CORE
3394 /*******************************************************************
3395 prepare to dump a core file - carefully!
3396 ********************************************************************/
3397 static BOOL dump_core(void)
3398 {
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));
3409
3410 #ifndef NO_GETRLIMIT
3411 #ifdef RLIMIT_CORE
3412   {
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));
3419   }
3420 #endif
3421 #endif
3422
3423
3424   DEBUG(0,("Dumping core in %s\n",dname));
3425   return(True);
3426 }
3427 #endif
3428
3429 /****************************************************************************
3430 exit the server
3431 ****************************************************************************/
3432 void exit_server(char *reason)
3433 {
3434   static int firsttime=1;
3435   int i;
3436
3437   if (!firsttime) exit(0);
3438   firsttime = 0;
3439
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
3460   }    
3461   DEBUG(3,("%s Server exit  (%s)\n",timestring(),reason?reason:""));
3462   exit(0);
3463 }
3464
3465 /****************************************************************************
3466 do some standard substitutions in a string
3467 ****************************************************************************/
3468 void standard_sub(int cnum,char *s)
3469 {
3470   if (!strchr(s,'%')) return;
3471
3472   if (VALID_CNUM(cnum))
3473     {
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);
3480       }
3481       string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3482     }
3483   standard_sub_basic(s);
3484 }
3485
3486 /*
3487 These flags determine some of the permissions required to do an operation 
3488
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.
3492 */
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)
3498
3499
3500 /* 
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!
3504 */
3505 struct smb_message_struct
3506 {
3507   int code;
3508   char *name;
3509   int (*fn)();
3510   int flags;
3511 #if PROFILING
3512   unsigned long time;
3513 #endif
3514 }
3515  smb_messages[] = {
3516
3517     /* CORE PROTOCOL */
3518
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},
3533
3534    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
3535    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3536    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
3537
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},
3546
3547    /* this is a Pathworks specific call, allowing the 
3548       changing of the root path */
3549    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
3550
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},
3560    
3561    /* CORE+ PROTOCOL FOLLOWS */
3562    
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},
3568    
3569    /* LANMAN1.0 PROTOCOL FOLLOWS */
3570    
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},
3583    
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},
3588    
3589    {SMBffirst,"SMBffirst",reply_search,AS_USER},
3590    {SMBfunique,"SMBfunique",reply_search,AS_USER},
3591    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3592
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},
3598
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},
3604
3605    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3606    
3607    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3608    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3609    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3610    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3611  };
3612
3613 /****************************************************************************
3614 return a string containing the function name of a SMB command
3615 ****************************************************************************/
3616 char *smb_fn_name(int type)
3617 {
3618   static char *unknown_name = "SMBunknown";
3619   static int num_smb_messages = 
3620     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3621   int match;
3622
3623   for (match=0;match<num_smb_messages;match++)
3624     if (smb_messages[match].code == type)
3625       break;
3626
3627   if (match == num_smb_messages)
3628     return(unknown_name);
3629
3630   return(smb_messages[match].name);
3631 }
3632
3633
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)
3638 {
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;
3644
3645 #if PROFILING
3646   struct timeval msg_start_time;
3647   struct timeval msg_end_time;
3648   static unsigned long total_time = 0;
3649
3650   GetTimeOfDay(&msg_start_time);
3651 #endif
3652
3653   if (pid == -1)
3654     pid = getpid();
3655
3656   errno = 0;
3657   last_message = type;
3658
3659   /* make sure this is an SMB packet */
3660   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3661     {
3662       DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3663       return(-1);
3664     }
3665
3666   for (match=0;match<num_smb_messages;match++)
3667     if (smb_messages[match].code == type)
3668       break;
3669
3670   if (match == num_smb_messages)
3671     {
3672       DEBUG(0,("Unknown message type %d!\n",type));
3673       outsize = reply_unknown(inbuf,outbuf);
3674     }
3675   else
3676     {
3677       DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3678       if (smb_messages[match].fn)
3679         {
3680           int cnum = SVAL(inbuf,smb_tid);
3681           int flags = smb_messages[match].flags;
3682           int uid = SVAL(inbuf,smb_uid);
3683
3684           /* does this protocol need to be run as root? */
3685           if (!(flags & AS_USER))
3686             unbecome_user();
3687
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));
3691
3692           /* does it need write permission? */
3693           if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3694             return(ERROR(ERRSRV,ERRaccess));
3695
3696           /* ipc services are limited */
3697           if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3698             return(ERROR(ERRSRV,ERRaccess));        
3699
3700           /* load service specific parameters */
3701           if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3702             return(ERROR(ERRSRV,ERRaccess));
3703
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));
3707
3708           last_inbuf = inbuf;
3709
3710           outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3711         }
3712       else
3713         {
3714           outsize = reply_unknown(inbuf,outbuf);
3715         }
3716     }
3717
3718 #if PROFILING
3719   GetTimeOfDay(&msg_end_time);
3720   if (!(smb_messages[match].flags & TIME_INIT))
3721     {
3722       smb_messages[match].time = 0;
3723       smb_messages[match].flags |= TIME_INIT;
3724     }
3725   {
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;
3731   }
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
3736
3737   return(outsize);
3738 }
3739
3740
3741 /****************************************************************************
3742 construct a chained reply and add it to the already made reply
3743
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
3751
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)
3755 {
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;
3763  
3764
3765   chain_size += PTR_DIFF(outbuf2,outbuf) - smb_wct;
3766   if (was_inchain)
3767     outbuf = last_outbuf;
3768   else
3769     insize_deleted = 0;
3770
3771
3772   insize_deleted = 0;
3773   inbuf2 -= insize_deleted;
3774   insize_remaining = size - PTR_DIFF(inbuf2,inbuf);
3775   insize_deleted += size - (insize_remaining + smb_wct);
3776
3777   in_chain = True;
3778   last_outbuf = outbuf;
3779
3780
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);
3784
3785   if (!ibuf || !obuf)
3786     {
3787       DEBUG(0,("Out of memory in chain reply\n"));
3788       return(ERROR(ERRSRV,ERRnoresource));
3789     }
3790
3791   ibuf += SMB_ALIGNMENT;
3792   obuf += SMB_ALIGNMENT;
3793
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;
3798
3799   /* create the out buffer */
3800   bzero(obuf,smb_size);
3801
3802   set_message(obuf,0,0,True);
3803   CVAL(obuf,smb_com) = CVAL(ibuf,smb_com);
3804   
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));
3816
3817   DEBUG(3,("Chained message\n"));
3818   show_msg(ibuf);
3819
3820   /* process the request */
3821   outsize = switch_message(type,ibuf,obuf,smb_wct+insize_remaining,
3822                            bufsize-chain_size);
3823
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));
3827
3828   /* and copy the data from the reply to the right spot */
3829   memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct);
3830
3831   /* free the allocated buffers */
3832   if (ibuf) free(ibuf-SMB_ALIGNMENT);
3833   if (obuf) free(obuf-SMB_ALIGNMENT);
3834
3835   in_chain = was_inchain;
3836
3837   /* return how much extra has been added to the packet */
3838   return(outsize - smb_wct);
3839 }
3840
3841
3842
3843 /****************************************************************************
3844   construct a reply to the incoming packet
3845 ****************************************************************************/
3846 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
3847 {
3848   int type = CVAL(inbuf,smb_com);
3849   int outsize = 0;
3850   int msg_type = CVAL(inbuf,0);
3851
3852   smb_last_time = time(NULL);
3853
3854   chain_size = 0;
3855
3856   bzero(outbuf,smb_size);
3857
3858   if (msg_type != 0)
3859     return(reply_special(inbuf,outbuf));  
3860
3861   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
3862   set_message(outbuf,0,0,True);
3863   
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));
3875
3876   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
3877
3878   if(outsize > 4)
3879     smb_setlen(outbuf,outsize - 4);
3880   return(outsize);
3881 }
3882
3883
3884 /****************************************************************************
3885   process commands from the client
3886 ****************************************************************************/
3887 void process(void )
3888 {
3889   static int trans_num = 0;
3890   int nread;
3891   extern struct from_host Client_info;
3892   extern int Client;
3893
3894   fromhost(Client,&Client_info);
3895   
3896   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3897   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
3898   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
3899     return;
3900
3901   InBuffer += SMB_ALIGNMENT;
3902   OutBuffer += SMB_ALIGNMENT;
3903
3904 #if PRIME_NMBD
3905   DEBUG(3,("priming nmbd\n"));
3906   {
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);
3912   }
3913 #endif    
3914
3915   last_user.cnum = -1;
3916   
3917   while (True)
3918     {
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;
3926
3927       if (deadtime <= 0)
3928         deadtime = DEFAULT_SMBD_TIMEOUT;
3929
3930       if (lp_readprediction())
3931         do_read_prediction();
3932
3933       {
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;
3942         }
3943       }
3944
3945       if (share_mode_pending) {
3946         unbecome_user();
3947         check_share_modes();
3948         share_mode_pending=False;
3949       }
3950
3951       errno = 0;      
3952
3953       for (counter=SMBD_SELECT_LOOP; 
3954            !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); 
3955            counter += SMBD_SELECT_LOOP)
3956         {
3957           int i;
3958           time_t t;
3959           BOOL allidle = True;
3960           extern int keepalive;
3961
3962           /* check for socket failure */
3963           if (errno == EBADF) {
3964             DEBUG(3,("%s Bad file descriptor - exiting\n",timestring()));
3965             return;
3966           }
3967
3968           t = time(NULL);
3969
3970           /* become root again if waiting */
3971           unbecome_user();
3972
3973           /* check for smb.conf reload */
3974           if (!(counter%SMBD_RELOAD_CHECK))
3975             reload_services(True);
3976
3977           /* check the share modes every 10 secs */
3978           if (!(counter%SHARE_MODES_CHECK))
3979             check_share_modes();
3980
3981           /* clean the share modes every 5 minutes */
3982           if (!(counter%SHARE_MODES_CLEAN))
3983             clean_share_files();
3984
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;
3989           }
3990
3991           if (keepalive && (counter-last_keepalive)>keepalive) {
3992             if (!send_keepalive(Client)) {
3993               DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
3994               return;
3995             }
3996             last_keepalive = counter;
3997           }
3998
3999           /* check for connection timeouts */
4000           for (i=0;i<MAX_CONNECTIONS;i++)
4001             if (Connections[i].open)
4002               {
4003                 /* close dirptrs on connections that are idle */
4004                 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
4005                   dptr_idlecnum(i);
4006
4007                 if (Connections[i].num_files_open > 0 ||
4008                     (t-Connections[i].lastused)<deadtime)
4009                   allidle = False;
4010               }
4011
4012           if (allidle && num_connections_open>0) {
4013             DEBUG(2,("%s Closing idle connection 2\n",timestring()));
4014             return;
4015           }
4016         }
4017
4018       msg_type = CVAL(InBuffer,0);
4019       msg_flags = CVAL(InBuffer,1);
4020       type = CVAL(InBuffer,smb_com);
4021
4022       len = smb_len(InBuffer);
4023
4024       DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
4025
4026       nread = len + 4;
4027       
4028       DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
4029
4030 #ifdef WITH_VTP
4031       if(trans_num == 1 && VT_Check(InBuffer)) {
4032         VT_Process();
4033         return;
4034       }
4035 #endif
4036
4037
4038       if (msg_type == 0)
4039         show_msg(InBuffer);
4040
4041       nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
4042       
4043       if(nread > 0) {
4044         if (CVAL(OutBuffer,0) == 0)
4045           show_msg(OutBuffer);
4046         
4047         if (nread != smb_len(OutBuffer) + 4) 
4048           {
4049             DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
4050                      nread,
4051                      smb_len(OutBuffer)));
4052           }
4053         else
4054           send_smb(Client,OutBuffer);
4055       }
4056       trans_num++;
4057     }
4058 }
4059
4060
4061 /****************************************************************************
4062   initialise connect, service and file structs
4063 ****************************************************************************/
4064 static void init_structs(void )
4065 {
4066   int i;
4067   get_myname(myhostname,&myip);
4068
4069   for (i=0;i<MAX_CONNECTIONS;i++)
4070     {
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,"");
4079     }
4080
4081   for (i=0;i<MAX_OPEN_FILES;i++)
4082     {
4083       Files[i].open = False;
4084       string_init(&Files[i].name,"");
4085     }
4086
4087   init_dptrs();
4088 }
4089
4090 /****************************************************************************
4091 usage on the program
4092 ****************************************************************************/
4093 void usage(char *pname)
4094 {
4095   DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4096
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");
4107 }
4108
4109
4110 /****************************************************************************
4111   main program
4112 ****************************************************************************/
4113 int main(int argc,char *argv[])
4114 {
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;
4121
4122 #ifdef NEED_AUTH_PARAMETERS
4123   set_auth_parameters(argc,argv);
4124 #endif
4125
4126 #ifdef SecureWare
4127   setluid(0);
4128 #endif
4129
4130   append_log = True;
4131
4132   TimeInit();
4133
4134   strcpy(debugf,SMBLOGFILE);  
4135
4136   setup_logging(argv[0],False);
4137
4138   charset_initialise();
4139
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
4150
4151   fault_setup(exit_server);
4152
4153   umask(0777 & ~DEF_CREATE_MASK);
4154
4155   initial_uid = geteuid();
4156   initial_gid = getegid();
4157
4158   if (initial_gid != 0 && initial_uid == 0)
4159     {
4160 #ifdef HPUX
4161       setresgid(0,0,0);
4162 #else
4163       setgid(0);
4164       setegid(0);
4165 #endif
4166     }
4167
4168   initial_uid = geteuid();
4169   initial_gid = getegid();
4170
4171
4172   /* this is for people who can't start the program correctly */
4173   while (argc > 1 && (*argv[1] != '-'))
4174     {
4175       argv++;
4176       argc--;
4177     }
4178
4179   while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPa")) != EOF)
4180     switch (opt)
4181       {
4182       case 'O':
4183         strcpy(user_socket_options,optarg);
4184         break;
4185       case 'i':
4186         strcpy(scope,optarg);
4187         break;
4188       case 'P':
4189         {
4190           extern BOOL passive;
4191           passive = True;
4192         }
4193         break;  
4194       case 's':
4195         strcpy(servicesf,optarg);
4196         break;
4197       case 'l':
4198         strcpy(debugf,optarg);
4199         break;
4200       case 'a':
4201         {
4202           extern BOOL append_log;
4203           append_log = !append_log;
4204         }
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);
4225       }
4226
4227   reopen_logs();
4228
4229   DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4230   DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
4231
4232   GetWd(OriginalDir);
4233
4234 #ifndef NO_GETRLIMIT
4235 #ifdef RLIMIT_NOFILE
4236   {
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));
4243   }
4244 #endif
4245 #endif
4246
4247   
4248   DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4249         getuid(),getgid(),geteuid(),getegid()));
4250
4251   if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4252     {
4253       DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4254       exit(1);
4255     }
4256
4257   init_structs();
4258
4259   if (!reload_services(False))
4260     return(-1); 
4261
4262 #ifndef NO_SIGNAL_TEST
4263   signal(SIGHUP,SIGNAL_CAST sig_hup);
4264 #endif
4265   
4266   DEBUG(3,("%s loaded services\n",timestring()));
4267
4268   if (!is_daemon && !is_a_socket(0))
4269     {
4270       DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4271       is_daemon = True;
4272     }
4273
4274   if (is_daemon)
4275     {
4276       DEBUG(3,("%s becoming a daemon\n",timestring()));
4277       become_daemon();
4278     }
4279
4280   if (open_sockets(is_daemon,port))
4281     {      
4282       /* possibly reload the services file. */
4283       reload_services(True);
4284
4285       maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
4286
4287       if (*lp_rootdir())
4288         {
4289           if (sys_chroot(lp_rootdir()) == 0)
4290             DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4291         }
4292
4293       process();
4294       close_sockets();
4295     }
4296   exit_server("normal exit");
4297   return(0);
4298 }
4299
4300