added "hide files" option.
[kai/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-1997
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 "trans2.h"
24
25 pstring servicesf = CONFIGFILE;
26 extern pstring debugf;
27 extern pstring sesssetup_user;
28 extern fstring myworkgroup;
29
30 char *InBuffer = NULL;
31 char *OutBuffer = NULL;
32 char *last_inbuf = NULL;
33
34 int am_parent = 1;
35 int atexit_set = 0;
36
37 /* the last message the was processed */
38 int last_message = -1;
39
40 /* a useful macro to debug the last message processed */
41 #define LAST_MESSAGE() smb_fn_name(last_message)
42
43 extern pstring scope;
44 extern int DEBUGLEVEL;
45 extern int case_default;
46 extern BOOL case_sensitive;
47 extern BOOL case_preserve;
48 extern BOOL use_mangled_map;
49 extern BOOL short_case_preserve;
50 extern BOOL case_mangle;
51 extern time_t smb_last_time;
52
53 extern int smb_read_error;
54
55 extern pstring user_socket_options;
56
57 connection_struct Connections[MAX_CONNECTIONS];
58 files_struct Files[MAX_OPEN_FILES];
59
60 /*
61  * Indirection for file fd's. Needed as POSIX locking
62  * is based on file/process, not fd/process.
63  */
64 file_fd_struct FileFd[MAX_OPEN_FILES];
65 int max_file_fd_used = 0;
66
67 extern int Protocol;
68
69 /* 
70  * Size of data we can send to client. Set
71  *  by the client for all protocols above CORE.
72  *  Set by us for CORE protocol.
73  */
74 int max_send = BUFFER_SIZE;
75 /*
76  * Size of the data we can receive. Set by us.
77  * Can be modified by the max xmit parameter.
78  */
79 int max_recv = BUFFER_SIZE;
80
81 /* a fnum to use when chaining */
82 int chain_fnum = -1;
83
84 /* number of open connections */
85 static int num_connections_open = 0;
86
87 extern fstring remote_machine;
88
89 pstring OriginalDir;
90
91 /* these can be set by some functions to override the error codes */
92 int unix_ERR_class=SUCCESS;
93 int unix_ERR_code=0;
94
95
96 extern int extra_time_offset;
97
98 extern pstring myhostname;
99
100 static int find_free_connection(int hash);
101
102 /* for readability... */
103 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
104 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
105 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
106 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
107 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
108
109 /****************************************************************************
110   when exiting, take the whole family
111 ****************************************************************************/
112 void  *dflt_sig(void)
113 {
114   exit_server("caught signal");
115   return 0; /* Keep -Wall happy :-) */
116 }
117 /****************************************************************************
118   Send a SIGTERM to our process group.
119 *****************************************************************************/
120 void  killkids(void)
121 {
122   if(am_parent) kill(0,SIGTERM);
123 }
124
125 /****************************************************************************
126   change a dos mode to a unix mode
127     base permission for files:
128          everybody gets read bit set
129          dos readonly is represented in unix by removing everyone's write bit
130          dos archive is represented in unix by the user's execute bit
131          dos system is represented in unix by the group's execute bit
132          dos hidden is represented in unix by the other's execute bit
133          Then apply create mask,
134          then add force bits.
135     base permission for directories:
136          dos directory is represented in unix by unix's dir bit and the exec bit
137          Then apply create mask,
138          then add force bits.
139 ****************************************************************************/
140 mode_t unix_mode(int cnum,int dosmode)
141 {
142   mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
143
144   if ( !IS_DOS_READONLY(dosmode) )
145     result |= (S_IWUSR | S_IWGRP | S_IWOTH);
146  
147   if (IS_DOS_DIR(dosmode)) {
148     /* We never make directories read only for the owner as under DOS a user
149        can always create a file in a read-only directory. */
150     result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
151     /* Apply directory mask */
152     result &= lp_dir_mode(SNUM(cnum));
153     /* Add in force bits */
154     result |= lp_force_dir_mode(SNUM(cnum));
155   } else { 
156     if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
157       result |= S_IXUSR;
158
159     if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
160       result |= S_IXGRP;
161  
162     if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
163       result |= S_IXOTH;  
164  
165     /* Apply mode mask */
166     result &= lp_create_mode(SNUM(cnum));
167     /* Add in force bits */
168     result |= lp_force_create_mode(SNUM(cnum));
169   }
170   return(result);
171 }
172
173
174 /****************************************************************************
175   change a unix mode to a dos mode
176 ****************************************************************************/
177 int dos_mode(int cnum,char *path,struct stat *sbuf)
178 {
179   int result = 0;
180   extern struct current_user current_user;
181
182   if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
183     if (!((sbuf->st_mode & S_IWOTH) ||
184           Connections[cnum].admin_user ||
185           ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
186           ((sbuf->st_mode & S_IWGRP) && 
187            in_group(sbuf->st_gid,current_user.gid,
188                     current_user.ngroups,current_user.igroups))))
189       result |= aRONLY;
190   } else {
191     if ((sbuf->st_mode & S_IWUSR) == 0)
192       result |= aRONLY;
193   }
194
195   if ((sbuf->st_mode & S_IXUSR) != 0)
196     result |= aARCH;
197
198   if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
199     result |= aSYSTEM;
200
201   if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
202     result |= aHIDDEN;   
203   
204   if (S_ISDIR(sbuf->st_mode))
205     result = aDIR | (result & aRONLY);
206
207 #if LINKS_READ_ONLY
208   if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
209     result |= aRONLY;
210 #endif
211
212   /* hide files with a name starting with a . */
213   if (lp_hide_dot_files(SNUM(cnum)))
214     {
215       char *p = strrchr(path,'/');
216       if (p)
217         p++;
218       else
219         p = path;
220       
221       if (p[0] == '.' && p[1] != '.' && p[1] != 0)
222         result |= aHIDDEN;
223     }
224
225   if (is_hidden_path(path))
226   {
227     result |= aHIDDEN;
228   }
229
230   return(result);
231 }
232
233
234 /*******************************************************************
235 chmod a file - but preserve some bits
236 ********************************************************************/
237 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
238 {
239   struct stat st1;
240   int mask=0;
241   int tmp;
242   int unixmode;
243
244   if (!st) {
245     st = &st1;
246     if (sys_stat(fname,st)) return(-1);
247   }
248
249   if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
250
251   if (dos_mode(cnum,fname,st) == dosmode) return(0);
252
253   unixmode = unix_mode(cnum,dosmode);
254
255   /* preserve the s bits */
256   mask |= (S_ISUID | S_ISGID);
257
258   /* preserve the t bit */
259 #ifdef S_ISVTX
260   mask |= S_ISVTX;
261 #endif
262
263   /* possibly preserve the x bits */
264   if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
265   if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
266   if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
267
268   unixmode |= (st->st_mode & mask);
269
270   /* if we previously had any r bits set then leave them alone */
271   if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
272     unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
273     unixmode |= tmp;
274   }
275
276   /* if we previously had any w bits set then leave them alone 
277    if the new mode is not rdonly */
278   if (!IS_DOS_READONLY(dosmode) &&
279       (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
280     unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
281     unixmode |= tmp;
282   }
283
284   return(sys_chmod(fname,unixmode));
285 }
286
287
288 /****************************************************************************
289 check if two filenames are equal
290
291 this needs to be careful about whether we are case sensitive
292 ****************************************************************************/
293 static BOOL fname_equal(char *name1, char *name2)
294 {
295   int l1 = strlen(name1);
296   int l2 = strlen(name2);
297
298   /* handle filenames ending in a single dot */
299   if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
300     {
301       BOOL ret;
302       name1[l1-1] = 0;
303       ret = fname_equal(name1,name2);
304       name1[l1-1] = '.';
305       return(ret);
306     }
307
308   if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
309     {
310       BOOL ret;
311       name2[l2-1] = 0;
312       ret = fname_equal(name1,name2);
313       name2[l2-1] = '.';
314       return(ret);
315     }
316
317   /* now normal filename handling */
318   if (case_sensitive)
319     return(strcmp(name1,name2) == 0);
320
321   return(strequal(name1,name2));
322 }
323
324
325 /****************************************************************************
326 mangle the 2nd name and check if it is then equal to the first name
327 ****************************************************************************/
328 static BOOL mangled_equal(char *name1, char *name2)
329 {
330   pstring tmpname;
331
332   if (is_8_3(name2, True))
333     return(False);
334
335   strcpy(tmpname,name2);
336   mangle_name_83(tmpname);
337
338   return(strequal(name1,tmpname));
339 }
340
341
342 /****************************************************************************
343 scan a directory to find a filename, matching without case sensitivity
344
345 If the name looks like a mangled name then try via the mangling functions
346 ****************************************************************************/
347 static BOOL scan_directory(char *path, char *name,int snum,BOOL docache)
348 {
349   void *cur_dir;
350   char *dname;
351   BOOL mangled;
352   pstring name2;
353
354   mangled = is_mangled(name);
355
356   /* handle null paths */
357   if (*path == 0)
358     path = ".";
359
360   if (docache && (dname = DirCacheCheck(path,name,snum))) {
361     strcpy(name, dname);        
362     return(True);
363   }      
364
365   if (mangled)
366     check_mangled_stack(name);
367
368   /* open the directory */
369   if (!(cur_dir = OpenDir(path))) 
370     {
371       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
372       return(False);
373     }
374
375   /* now scan for matching names */
376   while ((dname = ReadDirName(cur_dir))) 
377     {
378       if (*dname == '.' &&
379           (strequal(dname,".") || strequal(dname,"..")))
380         continue;
381
382       strcpy(name2,dname);
383       if (!name_map_mangle(name2,False,snum)) continue;
384
385       if ((mangled && mangled_equal(name,name2))
386           || fname_equal(name, name2))
387         {
388           /* we've found the file, change it's name and return */
389           if (docache) DirCacheAdd(path,name,dname,snum);
390           strcpy(name, dname);
391           CloseDir(cur_dir);
392           return(True);
393         }
394     }
395
396   CloseDir(cur_dir);
397   return(False);
398 }
399
400 /****************************************************************************
401 This routine is called to convert names from the dos namespace to unix
402 namespace. It needs to handle any case conversions, mangling, format
403 changes etc.
404
405 We assume that we have already done a chdir() to the right "root" directory
406 for this service.
407
408 The function will return False if some part of the name except for the last
409 part cannot be resolved
410
411 If the saved_last_component != 0, then the unmodified last component
412 of the pathname is returned there. This is used in an exceptional
413 case in reply_mv (so far). If saved_last_component == 0 then nothing
414 is returned there.
415 ****************************************************************************/
416 BOOL unix_convert(char *name,int cnum,pstring saved_last_component)
417 {
418   struct stat st;
419   char *start, *end;
420   pstring dirpath;
421
422   *dirpath = 0;
423   if(saved_last_component)
424     *saved_last_component = 0;
425
426   /* convert to basic unix format - removing \ chars and cleaning it up */
427   unix_format(name);
428   unix_clean_name(name);
429
430   /* names must be relative to the root of the service - trim any leading /.
431    also trim trailing /'s */
432   trim_string(name,"/","/");
433
434   /*
435    * Ensure saved_last_component is valid even if file exists.
436    */
437   if(saved_last_component) {
438     end = strrchr(name, '/');
439     if(end)
440       strcpy(saved_last_component, end + 1);
441     else
442       strcpy(saved_last_component, name);
443   }
444
445   if (!case_sensitive && 
446       (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
447     strnorm(name);
448
449   /* check if it's a printer file */
450   if (Connections[cnum].printer)
451     {
452       if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
453         {
454           char *s;
455           fstring name2;
456           sprintf(name2,"%.6s.XXXXXX",remote_machine);
457           /* sanitise the name */
458           for (s=name2 ; *s ; s++)
459             if (!issafe(*s)) *s = '_';
460           strcpy(name,(char *)mktemp(name2));     
461         }      
462       return(True);
463     }
464
465   /* stat the name - if it exists then we are all done! */
466   if (sys_stat(name,&st) == 0)
467     return(True);
468
469   DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
470
471   /* a special case - if we don't have any mangling chars and are case
472      sensitive then searching won't help */
473   if (case_sensitive && !is_mangled(name) && 
474       !lp_strip_dot() && !use_mangled_map)
475     return(False);
476
477   /* now we need to recursively match the name against the real 
478      directory structure */
479
480   start = name;
481   while (strncmp(start,"./",2) == 0)
482     start += 2;
483
484   /* now match each part of the path name separately, trying the names
485      as is first, then trying to scan the directory for matching names */
486   for (;start;start = (end?end+1:(char *)NULL)) 
487     {
488       /* pinpoint the end of this section of the filename */
489       end = strchr(start, '/');
490
491       /* chop the name at this point */
492       if (end)  *end = 0;
493
494       if(saved_last_component != 0)
495         strcpy(saved_last_component, end ? end + 1 : start);
496
497       /* check if the name exists up to this point */
498       if (sys_stat(name, &st) == 0) 
499         {
500           /* it exists. it must either be a directory or this must be
501              the last part of the path for it to be OK */
502           if (end && !(st.st_mode & S_IFDIR)) 
503             {
504               /* an intermediate part of the name isn't a directory */
505               DEBUG(5,("Not a dir %s\n",start));
506               *end = '/';
507               return(False);
508             }
509         }
510       else 
511         {
512           pstring rest;
513
514           *rest = 0;
515
516           /* remember the rest of the pathname so it can be restored
517              later */
518           if (end) strcpy(rest,end+1);
519
520           /* try to find this part of the path in the directory */
521           if (strchr(start,'?') || strchr(start,'*') ||
522               !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
523             {
524               if (end) 
525                 {
526                   /* an intermediate part of the name can't be found */
527                   DEBUG(5,("Intermediate not found %s\n",start));
528                   *end = '/';
529                   return(False);
530                 }
531               
532               /* just the last part of the name doesn't exist */
533               /* we may need to strupper() or strlower() it in case
534                  this conversion is being used for file creation 
535                  purposes */
536               /* if the filename is of mixed case then don't normalise it */
537               if (!case_preserve && 
538                   (!strhasupper(start) || !strhaslower(start)))         
539                 strnorm(start);
540
541               /* check on the mangled stack to see if we can recover the 
542                  base of the filename */
543               if (is_mangled(start))
544                 check_mangled_stack(start);
545
546               DEBUG(5,("New file %s\n",start));
547               return(True); 
548             }
549
550           /* restore the rest of the string */
551           if (end) 
552             {
553               strcpy(start+strlen(start)+1,rest);
554               end = start + strlen(start);
555             }
556         }
557
558       /* add to the dirpath that we have resolved so far */
559       if (*dirpath) strcat(dirpath,"/");
560       strcat(dirpath,start);
561
562       /* restore the / that we wiped out earlier */
563       if (end) *end = '/';
564     }
565   
566   /* the name has been resolved */
567   DEBUG(5,("conversion finished %s\n",name));
568   return(True);
569 }
570
571
572 /****************************************************************************
573 normalise for DOS usage 
574 ****************************************************************************/
575 static void disk_norm(int *bsize,int *dfree,int *dsize)
576 {
577   /* check if the disk is beyond the max disk size */
578   int maxdisksize = lp_maxdisksize();
579   if (maxdisksize) {
580     /* convert to blocks - and don't overflow */
581     maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
582     if (*dsize > maxdisksize) *dsize = maxdisksize;
583     if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop 
584                                                          applications getting 
585                                                          div by 0 errors */
586   }  
587
588   while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) 
589     {
590       *dfree /= 2;
591       *dsize /= 2;
592       *bsize *= 2;
593       if (*bsize > WORDMAX )
594         {
595           *bsize = WORDMAX;
596           if (*dsize > WORDMAX)
597             *dsize = WORDMAX;
598           if (*dfree >  WORDMAX)
599             *dfree = WORDMAX;
600           break;
601         }
602     }
603 }
604
605 /****************************************************************************
606   return number of 1K blocks available on a path and total number 
607 ****************************************************************************/
608 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
609 {
610   char *df_command = lp_dfree_command();
611   int dfree_retval;
612 #ifdef QUOTAS
613   int dfreeq_retval;
614   int dfreeq = 0;
615   int bsizeq = *bsize;
616   int dsizeq = *dsize;
617 #endif
618
619 #ifndef NO_STATFS
620 #ifdef USE_STATVFS
621   struct statvfs fs;
622 #else
623 #ifdef ULTRIX
624   struct fs_data fs;
625 #else
626   struct statfs fs;
627 #endif
628 #endif
629 #endif
630
631   /* possibly use system() to get the result */
632   if (df_command && *df_command)
633     {
634       int ret;
635       pstring syscmd;
636       pstring outfile;
637           
638       sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
639       sprintf(syscmd,"%s %s",df_command,path);
640       standard_sub_basic(syscmd);
641
642       ret = smbrun(syscmd,outfile,False);
643       DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
644           
645       {
646         FILE *f = fopen(outfile,"r");   
647         *dsize = 0;
648         *dfree = 0;
649         *bsize = 1024;
650         if (f)
651           {
652             fscanf(f,"%d %d %d",dsize,dfree,bsize);
653             fclose(f);
654           }
655         else
656           DEBUG(0,("Can't open %s\n",outfile));
657       }
658           
659       unlink(outfile);
660       disk_norm(bsize,dfree,dsize);
661       dfree_retval = ((*bsize)/1024)*(*dfree);
662 #ifdef QUOTAS
663       /* Ensure we return the min value between the users quota and
664          what's free on the disk. Thanks to Albrecht Gebhardt 
665          <albrecht.gebhardt@uni-klu.ac.at> for this fix.
666       */
667       if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
668         {
669           disk_norm(&bsizeq, &dfreeq, &dsizeq);
670           dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
671           dfree_retval =  ( dfree_retval < dfreeq_retval ) ? 
672                            dfree_retval : dfreeq_retval ;
673           /* maybe dfree and dfreeq are calculated using different bsizes 
674              so convert dfree from bsize into bsizeq */
675           *dfree = ((*dfree) * (*bsize)) / (bsizeq);
676           *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; 
677           *bsize = bsizeq;
678           *dsize = dsizeq;
679         }
680 #endif
681       return(dfree_retval);
682     }
683
684 #ifdef NO_STATFS
685   DEBUG(1,("Warning - no statfs function\n"));
686   return(1);
687 #else
688 #ifdef STATFS4
689   if (statfs(path,&fs,sizeof(fs),0) != 0)
690 #else
691 #ifdef USE_STATVFS
692     if (statvfs(path, &fs))
693 #else
694 #ifdef STATFS3
695       if (statfs(path,&fs,sizeof(fs)) == -1)     
696 #else
697         if (statfs(path,&fs) == -1)
698 #endif /* STATFS3 */
699 #endif /* USE_STATVFS */
700 #endif /* STATFS4 */
701           {
702             DEBUG(3,("dfree call failed code errno=%d\n",errno));
703             *bsize = 1024;
704             *dfree = 1;
705             *dsize = 1;
706             return(((*bsize)/1024)*(*dfree));
707           }
708
709 #ifdef ULTRIX
710   *bsize = 1024;
711   *dfree = fs.fd_req.bfree;
712   *dsize = fs.fd_req.btot;
713 #else
714 #ifdef USE_STATVFS
715   *bsize = fs.f_frsize;
716 #else
717 #ifdef USE_F_FSIZE
718   /* eg: osf1 has f_fsize = fundamental filesystem block size, 
719      f_bsize = optimal transfer block size (MX: 94-04-19) */
720   *bsize = fs.f_fsize;
721 #else
722   *bsize = fs.f_bsize;
723 #endif /* STATFS3 */
724 #endif /* USE_STATVFS */
725
726 #ifdef STATFS4
727   *dfree = fs.f_bfree;
728 #else
729   *dfree = fs.f_bavail;
730 #endif /* STATFS4 */
731   *dsize = fs.f_blocks;
732 #endif /* ULTRIX */
733
734 #if defined(SCO) || defined(ISC) || defined(MIPS)
735   *bsize = 512;
736 #endif
737
738 /* handle rediculous bsize values - some OSes are broken */
739 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
740
741   disk_norm(bsize,dfree,dsize);
742
743   if (*bsize < 256)
744     *bsize = 512;
745   if ((*dsize)<1)
746     {
747       DEBUG(0,("dfree seems to be broken on your system\n"));
748       *dsize = 20*1024*1024/(*bsize);
749       *dfree = MAX(1,*dfree);
750     }
751   dfree_retval = ((*bsize)/1024)*(*dfree);
752 #ifdef QUOTAS
753   /* Ensure we return the min value between the users quota and
754      what's free on the disk. Thanks to Albrecht Gebhardt 
755      <albrecht.gebhardt@uni-klu.ac.at> for this fix.
756   */
757   if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
758     {
759       disk_norm(&bsizeq, &dfreeq, &dsizeq);
760       dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
761       dfree_retval = ( dfree_retval < dfreeq_retval ) ? 
762                        dfree_retval : dfreeq_retval ;
763       /* maybe dfree and dfreeq are calculated using different bsizes 
764          so convert dfree from bsize into bsizeq */
765       *dfree = ((*dfree) * (*bsize)) / (bsizeq);
766       *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
767       *bsize = bsizeq;
768       *dsize = dsizeq;
769     }
770 #endif
771   return(dfree_retval);
772 #endif
773 }
774
775
776 /****************************************************************************
777 wrap it to get filenames right
778 ****************************************************************************/
779 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
780 {
781   return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
782 }
783
784
785
786 /****************************************************************************
787 check a filename - possibly caling reducename
788
789 This is called by every routine before it allows an operation on a filename.
790 It does any final confirmation necessary to ensure that the filename is
791 a valid one for the user to access.
792 ****************************************************************************/
793 BOOL check_name(char *name,int cnum)
794 {
795   BOOL ret;
796
797   errno = 0;
798
799   if( is_vetoed_path(name)) 
800     {
801       DEBUG(5,("file path name %s vetoed\n",name));
802       return(0);
803     }
804
805   ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
806   if (!ret)
807     DEBUG(5,("check_name on %s failed\n",name));
808
809   return(ret);
810 }
811
812 /****************************************************************************
813 check a filename - possibly caling reducename
814 ****************************************************************************/
815 static void check_for_pipe(char *fname)
816 {
817   /* special case of pipe opens */
818   char s[10];
819   StrnCpy(s,fname,9);
820   strlower(s);
821   if (strstr(s,"pipe/"))
822     {
823       DEBUG(3,("Rejecting named pipe open for %s\n",fname));
824       unix_ERR_class = ERRSRV;
825       unix_ERR_code = ERRaccess;
826     }
827 }
828
829 /****************************************************************************
830 fd support routines - attempt to do a sys_open
831 ****************************************************************************/
832
833 int fd_attempt_open(char *fname, int flags, int mode)
834 {
835   int fd = sys_open(fname,flags,mode);
836
837   /* Fix for files ending in '.' */
838   if((fd == -1) && (errno == ENOENT) &&
839      (strchr(fname,'.')==NULL))
840     {
841       strcat(fname,".");
842       fd = sys_open(fname,flags,mode);
843     }
844
845 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
846   if ((fd == -1) && (errno == ENAMETOOLONG))
847     {
848       int max_len;
849       char *p = strrchr(fname, '/');
850
851       if (p == fname)   /* name is "/xxx" */
852         {
853           max_len = pathconf("/", _PC_NAME_MAX);
854           p++;
855         }
856       else if ((p == NULL) || (p == fname))
857         {
858           p = fname;
859           max_len = pathconf(".", _PC_NAME_MAX);
860         }
861       else
862         {
863           *p = '\0';
864           max_len = pathconf(fname, _PC_NAME_MAX);
865           *p = '/';
866           p++;
867         }
868       if (strlen(p) > max_len)
869         {
870           char tmp = p[max_len];
871
872           p[max_len] = '\0';
873           if ((fd = sys_open(fname,flags,mode)) == -1)
874             p[max_len] = tmp;
875         }
876     }
877 #endif
878   return fd;
879 }
880
881 /****************************************************************************
882 fd support routines - attempt to find an already open file by dev
883 and inode - increments the ref_count of the returned file_fd_struct *.
884 ****************************************************************************/
885 file_fd_struct *fd_get_already_open(struct stat *sbuf)
886 {
887   int i;
888   file_fd_struct *fd_ptr;
889
890   if(sbuf == 0)
891     return 0;
892
893   for(i = 0; i <= max_file_fd_used; i++) {
894     fd_ptr = &FileFd[i];
895     if((fd_ptr->ref_count > 0) &&
896        (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
897        (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
898       fd_ptr->ref_count++;
899       DEBUG(3,
900        ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
901         i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
902       return fd_ptr;
903     }
904   }
905   return 0;
906 }
907
908 /****************************************************************************
909 fd support routines - attempt to find a empty slot in the FileFd array.
910 Increments the ref_count of the returned entry.
911 ****************************************************************************/
912 file_fd_struct *fd_get_new()
913 {
914   int i;
915   file_fd_struct *fd_ptr;
916
917   for(i = 0; i < MAX_OPEN_FILES; i++) {
918     fd_ptr = &FileFd[i];
919     if(fd_ptr->ref_count == 0) {
920       fd_ptr->dev = (uint32)-1;
921       fd_ptr->inode = (uint32)-1;
922       fd_ptr->fd = -1;
923       fd_ptr->fd_readonly = -1;
924       fd_ptr->fd_writeonly = -1;
925       fd_ptr->real_open_flags = -1;
926       fd_ptr->ref_count++;
927       /* Increment max used counter if neccessary, cuts down
928          on search time when re-using */
929       if(i > max_file_fd_used)
930         max_file_fd_used = i;
931       DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
932                i, fd_ptr->dev, fd_ptr->inode));
933       return fd_ptr;
934     }
935   }
936   DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
937 n"));
938   return 0;
939 }
940
941 /****************************************************************************
942 fd support routines - attempt to re-open an already open fd as O_RDWR.
943 Save the already open fd (we cannot close due to POSIX file locking braindamage.
944 ****************************************************************************/
945
946 void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
947 {
948   int fd = sys_open( fname, O_RDWR, mode);
949
950   if(fd == -1)
951     return;
952
953   if(fd_ptr->real_open_flags == O_RDONLY)
954     fd_ptr->fd_readonly = fd_ptr->fd;
955   if(fd_ptr->real_open_flags == O_WRONLY)
956     fd_ptr->fd_writeonly = fd_ptr->fd;
957
958   fd_ptr->fd = fd;
959   fd_ptr->real_open_flags = O_RDWR;
960 }
961
962 /****************************************************************************
963 fd support routines - attempt to close the file referenced by this fd.
964 Decrements the ref_count and returns it.
965 ****************************************************************************/
966 int fd_attempt_close(file_fd_struct *fd_ptr)
967 {
968   DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
969            fd_ptr - &FileFd[0],
970            fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
971            fd_ptr->real_open_flags,
972            fd_ptr->ref_count));
973   if(fd_ptr->ref_count > 0) {
974     fd_ptr->ref_count--;
975     if(fd_ptr->ref_count == 0) {
976       if(fd_ptr->fd != -1)
977         close(fd_ptr->fd);
978       if(fd_ptr->fd_readonly != -1)
979         close(fd_ptr->fd_readonly);
980       if(fd_ptr->fd_writeonly != -1)
981         close(fd_ptr->fd_writeonly);
982       fd_ptr->fd = -1;
983       fd_ptr->fd_readonly = -1;
984       fd_ptr->fd_writeonly = -1;
985       fd_ptr->real_open_flags = -1;
986       fd_ptr->dev = (uint32)-1;
987       fd_ptr->inode = (uint32)-1;
988     }
989   } 
990  return fd_ptr->ref_count;
991 }
992
993 /****************************************************************************
994 open a file
995 ****************************************************************************/
996 static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
997 {
998   extern struct current_user current_user;
999   pstring fname;
1000   struct stat statbuf;
1001   file_fd_struct *fd_ptr;
1002
1003   Files[fnum].open = False;
1004   Files[fnum].fd_ptr = 0;
1005   errno = EPERM;
1006
1007   strcpy(fname,fname1);
1008
1009   /* check permissions */
1010   if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
1011     {
1012       DEBUG(3,("Permission denied opening %s\n",fname));
1013       check_for_pipe(fname);
1014       return;
1015     }
1016
1017   /* this handles a bug in Win95 - it doesn't say to create the file when it 
1018      should */
1019   if (Connections[cnum].printer)
1020     flags |= O_CREAT;
1021
1022 /*
1023   if (flags == O_WRONLY)
1024     DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
1025 */
1026
1027 #if UTIME_WORKAROUND
1028   /* XXXX - is this OK?? */
1029   /* this works around a utime bug but can cause other problems */
1030   if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
1031     sys_unlink(fname);
1032 #endif
1033
1034   /*
1035    * Ensure we have a valid struct stat so we can search the
1036    * open fd table.
1037    */
1038   if(sbuf == 0) {
1039     if(stat(fname, &statbuf) < 0) {
1040       if(errno != ENOENT) {
1041         DEBUG(3,("Error doing stat on file %s (%s)\n",
1042                  fname,strerror(errno)));
1043
1044         check_for_pipe(fname);
1045         return;
1046       }
1047       sbuf = 0;
1048     } else {
1049       sbuf = &statbuf;
1050     }
1051   }
1052
1053   /*
1054    * Check to see if we have this file already
1055    * open. If we do, just use the already open fd and increment the
1056    * reference count (fd_get_already_open increments the ref_count).
1057    */
1058   if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
1059
1060     int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
1061
1062     /* File was already open. */
1063     if((flags & O_CREAT) && (flags & O_EXCL)) {
1064       fd_ptr->ref_count--;
1065       errno = EEXIST;
1066       return;
1067     }
1068
1069     /* 
1070      * If not opened O_RDWR try
1071      * and do that here - a chmod may have been done
1072      * between the last open and now. 
1073      */
1074     if(fd_ptr->real_open_flags != O_RDWR)
1075       fd_attempt_reopen(fname, mode, fd_ptr);
1076
1077     /*
1078      * Ensure that if we wanted write access
1079      * it has been opened for write, and if we wanted read it
1080      * was open for read. 
1081      */
1082     if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1083        ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1084        ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1085       DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1086                fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1087       check_for_pipe(fname);
1088       fd_ptr->ref_count--;
1089       return;
1090     }
1091
1092   } else {
1093     int open_flags;
1094     /* We need to allocate a new file_fd_struct (this increments the
1095        ref_count). */
1096     if((fd_ptr = fd_get_new()) == 0)
1097       return;
1098     /*
1099      * Whatever the requested flags, attempt read/write access,
1100      * as we don't know what flags future file opens may require.
1101      * If this fails, try again with the required flags. 
1102      * Even if we open read/write when only read access was 
1103      * requested the setting of the can_write flag in
1104      * the file_struct will protect us from errant
1105      * write requests. We never need to worry about O_APPEND
1106      * as this is not set anywhere in Samba.
1107      */
1108     fd_ptr->real_open_flags = O_RDWR;
1109     /* Set the flags as needed without the read/write modes. */
1110     open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1111     fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1112     /*
1113      * On some systems opening a file for R/W access on a read only
1114      * filesystems sets errno to EROFS.
1115      */
1116 #ifdef EROFS
1117     if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1118 #else /* No EROFS */
1119     if((fd_ptr->fd == -1) && (errno == EACCES)) {
1120 #endif /* EROFS */
1121       if(flags & O_WRONLY) {
1122         fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1123         fd_ptr->real_open_flags = O_WRONLY;
1124       } else {
1125         fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1126         fd_ptr->real_open_flags = O_RDONLY;
1127       }
1128     }
1129   }
1130
1131   if ((fd_ptr->fd >=0) && 
1132       Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1133     pstring dname;
1134     int dum1,dum2,dum3;
1135     char *p;
1136     strcpy(dname,fname);
1137     p = strrchr(dname,'/');
1138     if (p) *p = 0;
1139     if (sys_disk_free(dname,&dum1,&dum2,&dum3) < 
1140         lp_minprintspace(SNUM(cnum))) {
1141       fd_attempt_close(fd_ptr);
1142       Files[fnum].fd_ptr = 0;
1143       if(fd_ptr->ref_count == 0)
1144         sys_unlink(fname);
1145       errno = ENOSPC;
1146       return;
1147     }
1148   }
1149     
1150   if (fd_ptr->fd < 0)
1151     {
1152       DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1153                fname,strerror(errno),flags));
1154       /* Ensure the ref_count is decremented. */
1155       fd_attempt_close(fd_ptr);
1156       check_for_pipe(fname);
1157       return;
1158     }
1159
1160   if (fd_ptr->fd >= 0)
1161     {
1162       if(sbuf == 0) {
1163         /* Do the fstat */
1164         if(fstat(fd_ptr->fd, &statbuf) == -1) {
1165           /* Error - backout !! */
1166           DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1167                    fd_ptr->fd, fname,strerror(errno)));
1168           /* Ensure the ref_count is decremented. */
1169           fd_attempt_close(fd_ptr);
1170           return;
1171         }
1172         sbuf = &statbuf;
1173       }
1174       /* Set the correct entries in fd_ptr. */
1175       fd_ptr->dev = (uint32)sbuf->st_dev;
1176       fd_ptr->inode = (uint32)sbuf->st_ino;
1177
1178       Files[fnum].fd_ptr = fd_ptr;
1179       Connections[cnum].num_files_open++;
1180       Files[fnum].mode = sbuf->st_mode;
1181       GetTimeOfDay(&Files[fnum].open_time);
1182       Files[fnum].uid = current_user.id;
1183       Files[fnum].size = 0;
1184       Files[fnum].pos = -1;
1185       Files[fnum].open = True;
1186       Files[fnum].mmap_ptr = NULL;
1187       Files[fnum].mmap_size = 0;
1188       Files[fnum].can_lock = True;
1189       Files[fnum].can_read = ((flags & O_WRONLY)==0);
1190       Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1191       Files[fnum].share_mode = 0;
1192       Files[fnum].print_file = Connections[cnum].printer;
1193       Files[fnum].modified = False;
1194       Files[fnum].cnum = cnum;
1195       string_set(&Files[fnum].name,dos_to_unix(fname,False));
1196       Files[fnum].wbmpx_ptr = NULL;      
1197
1198       /*
1199        * If the printer is marked as postscript output a leading
1200        * file identifier to ensure the file is treated as a raw
1201        * postscript file.
1202        * This has a similar effect as CtrlD=0 in WIN.INI file.
1203        * tim@fsg.com 09/06/94
1204        */
1205       if (Files[fnum].print_file && POSTSCRIPT(cnum) && 
1206           Files[fnum].can_write) 
1207         {
1208           DEBUG(3,("Writing postscript line\n"));
1209           write_file(fnum,"%!\n",3);
1210         }
1211       
1212       DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1213                timestring(),Connections[cnum].user,fname,
1214                BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
1215                Connections[cnum].num_files_open,fnum));
1216
1217     }
1218
1219 #if USE_MMAP
1220   /* mmap it if read-only */
1221   if (!Files[fnum].can_write)
1222     {
1223       Files[fnum].mmap_size = file_size(fname);
1224       Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
1225                                           PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
1226
1227       if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
1228         {
1229           DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1230           Files[fnum].mmap_ptr = NULL;
1231         }
1232     }
1233 #endif
1234 }
1235
1236 /*******************************************************************
1237 sync a file
1238 ********************************************************************/
1239 void sync_file(int fnum)
1240 {
1241 #ifndef NO_FSYNC
1242   fsync(Files[fnum].fd_ptr->fd);
1243 #endif
1244 }
1245
1246 /****************************************************************************
1247 run a file if it is a magic script
1248 ****************************************************************************/
1249 static void check_magic(int fnum,int cnum)
1250 {
1251   if (!*lp_magicscript(SNUM(cnum)))
1252     return;
1253
1254   DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1255
1256   {
1257     char *p;
1258     if (!(p = strrchr(Files[fnum].name,'/')))
1259       p = Files[fnum].name;
1260     else
1261       p++;
1262
1263     if (!strequal(lp_magicscript(SNUM(cnum)),p))
1264       return;
1265   }
1266
1267   {
1268     int ret;
1269     pstring magic_output;
1270     pstring fname;
1271     strcpy(fname,Files[fnum].name);
1272
1273     if (*lp_magicoutput(SNUM(cnum)))
1274       strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1275     else
1276       sprintf(magic_output,"%s.out",fname);
1277
1278     chmod(fname,0755);
1279     ret = smbrun(fname,magic_output,False);
1280     DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1281     unlink(fname);
1282   }
1283 }
1284
1285
1286 /****************************************************************************
1287 close a file - possibly invalidating the read prediction
1288 ****************************************************************************/
1289 void close_file(int fnum)
1290 {
1291   files_struct *fs_p = &Files[fnum];
1292   int cnum = fs_p->cnum;
1293   uint32 dev = fs_p->fd_ptr->dev;
1294   uint32 inode = fs_p->fd_ptr->inode;
1295   share_lock_token token;
1296
1297   invalidate_read_prediction(fs_p->fd_ptr->fd);
1298   fs_p->open = False;
1299   Connections[cnum].num_files_open--;
1300   if(fs_p->wbmpx_ptr) 
1301     {
1302       free((char *)fs_p->wbmpx_ptr);
1303       fs_p->wbmpx_ptr = NULL;
1304     }
1305
1306 #if USE_MMAP
1307   if(fs_p->mmap_ptr) 
1308     {
1309       munmap(fs_p->mmap_ptr,fs_p->mmap_size);
1310       fs_p->mmap_ptr = NULL;
1311     }
1312 #endif
1313
1314   if (lp_share_modes(SNUM(cnum)))
1315   {
1316     lock_share_entry( cnum, dev, inode, &token);
1317     del_share_mode(token, fnum);
1318   }
1319
1320   fd_attempt_close(fs_p->fd_ptr);
1321
1322   if (lp_share_modes(SNUM(cnum)))
1323     unlock_share_entry( cnum, dev, inode, token);
1324
1325   /* NT uses smbclose to start a print - weird */
1326   if (fs_p->print_file)
1327     print_file(fnum);
1328
1329   /* check for magic scripts */
1330   check_magic(fnum,cnum);
1331
1332   DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1333            timestring(),Connections[cnum].user,fs_p->name,
1334            Connections[cnum].num_files_open));
1335 }
1336
1337 enum {AFAIL,AREAD,AWRITE,AALL};
1338
1339 /*******************************************************************
1340 reproduce the share mode access table
1341 ********************************************************************/
1342 static int access_table(int new_deny,int old_deny,int old_mode,
1343                         int share_pid,char *fname)
1344 {
1345   if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1346
1347   if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1348     if (old_deny == new_deny && share_pid == getpid()) 
1349         return(AALL);    
1350
1351     if (old_mode == 0) return(AREAD);
1352
1353     /* the new smbpub.zip spec says that if the file extension is
1354        .com, .dll, .exe or .sym then allow the open. I will force
1355        it to read-only as this seems sensible although the spec is
1356        a little unclear on this. */
1357     if ((fname = strrchr(fname,'.'))) {
1358       if (strequal(fname,".com") ||
1359           strequal(fname,".dll") ||
1360           strequal(fname,".exe") ||
1361           strequal(fname,".sym"))
1362         return(AREAD);
1363     }
1364
1365     return(AFAIL);
1366   }
1367
1368   switch (new_deny) 
1369     {
1370     case DENY_WRITE:
1371       if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1372       if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1373       if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1374       return(AFAIL);
1375     case DENY_READ:
1376       if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1377       if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1378       if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1379       return(AFAIL);
1380     case DENY_NONE:
1381       if (old_deny==DENY_WRITE) return(AREAD);
1382       if (old_deny==DENY_READ) return(AWRITE);
1383       if (old_deny==DENY_NONE) return(AALL);
1384       return(AFAIL);      
1385     }
1386   return(AFAIL);      
1387 }
1388
1389 /*******************************************************************
1390 check if the share mode on a file allows it to be deleted or unlinked
1391 return True if sharing doesn't prevent the operation
1392 ********************************************************************/
1393 BOOL check_file_sharing(int cnum,char *fname)
1394 {
1395   int i;
1396   int ret = False;
1397   min_share_mode_entry *old_shares = 0;
1398   int num_share_modes;
1399   struct stat sbuf;
1400   share_lock_token token;
1401   int pid = getpid();
1402
1403   if(!lp_share_modes(SNUM(cnum)))
1404     return True;
1405
1406   if (stat(fname,&sbuf) == -1) return(True);
1407
1408   lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token);
1409   num_share_modes = get_share_modes(cnum, token, 
1410                      (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares);
1411
1412   for( i = 0; i < num_share_modes; i++)
1413   {
1414     if (old_shares[i].share_mode != DENY_DOS)
1415       goto free_and_exit;
1416
1417     if(old_shares[i].pid != pid)
1418       goto free_and_exit;
1419   }
1420
1421   /* XXXX exactly what share mode combinations should be allowed for
1422      deleting/renaming? */
1423   /* If we got here then either there were no share modes or
1424      all share modes were DENY_DOS and the pid == getpid() */
1425   ret = True;
1426
1427 free_and_exit:
1428
1429   unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token);
1430   if(old_shares != NULL)
1431     free((char *)old_shares);
1432   return(ret);
1433 }
1434
1435 /****************************************************************************
1436   C. Hoch 11/22/95
1437   Helper for open_file_shared. 
1438   Truncate a file after checking locking; close file if locked.
1439   **************************************************************************/
1440 static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, 
1441        BOOL *share_locked)
1442 {
1443   if (Files[fnum].can_write){
1444     if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1445       /* If share modes are in force for this connection we
1446          have the share entry locked. Unlock it before closing. */
1447       if (*share_locked && lp_share_modes(SNUM(cnum)))
1448         unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, 
1449                             Files[fnum].fd_ptr->inode, token);
1450       close_file(fnum);   
1451       /* Share mode no longer locked. */
1452       *share_locked = False;
1453       errno = EACCES;
1454       unix_ERR_class = ERRDOS;
1455       unix_ERR_code = ERRlock;
1456     }
1457     else
1458       ftruncate(Files[fnum].fd_ptr->fd,0); 
1459   }
1460 }
1461
1462
1463 /****************************************************************************
1464 open a file with a share mode
1465 ****************************************************************************/
1466 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1467                       int mode,int *Access,int *action)
1468 {
1469   files_struct *fs_p = &Files[fnum];
1470   int flags=0;
1471   int flags2=0;
1472   int deny_mode = (share_mode>>4)&7;
1473   struct stat sbuf;
1474   BOOL file_existed = file_exist(fname,&sbuf);
1475   BOOL share_locked = False;
1476   BOOL fcbopen = False;
1477   share_lock_token token;
1478   uint32 dev = 0;
1479   uint32 inode = 0;
1480
1481   fs_p->open = False;
1482   fs_p->fd_ptr = 0;
1483
1484   /* this is for OS/2 EAs - try and say we don't support them */
1485   if (strstr(fname,".+,;=[].")) 
1486   {
1487     unix_ERR_class = ERRDOS;
1488     unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1489     return;
1490   }
1491
1492   if ((ofun & 0x3) == 0 && file_existed)  
1493   {
1494     errno = EEXIST;
1495     return;
1496   }
1497       
1498   if (ofun & 0x10)
1499     flags2 |= O_CREAT;
1500   if ((ofun & 0x3) == 2)
1501     flags2 |= O_TRUNC;
1502
1503   /* note that we ignore the append flag as 
1504      append does not mean the same thing under dos and unix */
1505
1506   switch (share_mode&0xF)
1507   {
1508     case 1: 
1509       flags = O_WRONLY; 
1510       break;
1511     case 0xF: 
1512       fcbopen = True;
1513       flags = O_RDWR; 
1514       break;
1515     case 2: 
1516       flags = O_RDWR; 
1517       break;
1518     default:
1519       flags = O_RDONLY;
1520       break;
1521   }
1522   
1523   if (flags != O_RDONLY && file_existed && 
1524       (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) 
1525   {
1526     if (!fcbopen) 
1527     {
1528       errno = EACCES;
1529       return;
1530     }
1531     flags = O_RDONLY;
1532   }
1533
1534   if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) 
1535   {
1536     DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1537     errno = EINVAL;
1538     return;
1539   }
1540
1541   if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1542
1543   if (lp_share_modes(SNUM(cnum))) 
1544   {
1545     int num_shares = 0;
1546     int i;
1547     min_share_mode_entry *old_shares = 0;
1548
1549
1550     if (file_existed)
1551     {
1552       dev = (uint32)sbuf.st_dev;
1553       inode = (uint32)sbuf.st_ino;
1554       lock_share_entry(cnum, dev, inode, &token);
1555       share_locked = True;
1556       num_shares = get_share_modes(cnum, token, dev, inode, &old_shares);
1557     }
1558
1559     for(i = 0; i < num_shares; i++)
1560     {
1561       /* someone else has a share lock on it, check to see 
1562          if we can too */
1563       int old_open_mode = old_shares[i].share_mode &0xF;
1564       int old_deny_mode = (old_shares[i].share_mode >>4)&7;
1565
1566       if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) 
1567       {
1568         DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
1569                  deny_mode,old_deny_mode,old_open_mode,fname));
1570         free((char *)old_shares);
1571         if(share_locked)
1572           unlock_share_entry(cnum, dev, inode, token);
1573         errno = EACCES;
1574         unix_ERR_class = ERRDOS;
1575         unix_ERR_code = ERRbadshare;
1576         return;
1577       }
1578
1579       {
1580         int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1581                                           old_shares[i].pid,fname);
1582
1583         if ((access_allowed == AFAIL) ||
1584             (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
1585             (access_allowed == AREAD && flags == O_WRONLY) ||
1586             (access_allowed == AWRITE && flags == O_RDONLY)) 
1587         {
1588           DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1589                    deny_mode,old_deny_mode,old_open_mode,
1590                    old_shares[i].pid,fname,
1591                    access_allowed));
1592           free((char *)old_shares);
1593           if(share_locked)
1594             unlock_share_entry(cnum, dev, inode, token);
1595           errno = EACCES;
1596           unix_ERR_class = ERRDOS;
1597           unix_ERR_code = ERRbadshare;
1598           return;
1599         }
1600         
1601         if (access_allowed == AREAD)
1602           flags = O_RDONLY;
1603         
1604         if (access_allowed == AWRITE)
1605           flags = O_WRONLY;
1606       }
1607     }
1608     if(old_shares != 0)
1609       free((char *)old_shares);
1610   }
1611
1612   DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1613            flags,flags2,mode));
1614
1615   open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1616   if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen) 
1617   {
1618     flags = O_RDONLY;
1619     open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1620   }
1621
1622   if (fs_p->open) 
1623   {
1624     int open_mode=0;
1625
1626     if((share_locked == False) && lp_share_modes(SNUM(cnum)))
1627     {
1628       /* We created the file - thus we must now lock the share entry before creating it. */
1629       dev = fs_p->fd_ptr->dev;
1630       inode = fs_p->fd_ptr->inode;
1631       lock_share_entry(cnum, dev, inode, &token);
1632       share_locked = True;
1633     }
1634
1635     switch (flags) 
1636     {
1637       case O_RDONLY:
1638         open_mode = 0;
1639         break;
1640       case O_RDWR:
1641         open_mode = 2;
1642         break;
1643       case O_WRONLY:
1644         open_mode = 1;
1645         break;
1646     }
1647
1648     fs_p->share_mode = (deny_mode<<4) | open_mode;
1649
1650     if (Access)
1651       (*Access) = open_mode;
1652
1653     if (action) 
1654     {
1655       if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1656       if (!file_existed) *action = 2;
1657       if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1658     }
1659     /* We must create the share mode entry before truncate as
1660        truncate can fail due to locking and have to close the
1661        file (which expects the share_mode_entry to be there).
1662      */
1663     if (lp_share_modes(SNUM(cnum)))
1664       set_share_mode(token, fnum);
1665
1666     if ((flags2&O_TRUNC) && file_existed)
1667       truncate_unless_locked(fnum,cnum,token,&share_locked);
1668   }
1669
1670   if (share_locked && lp_share_modes(SNUM(cnum)))
1671     unlock_share_entry( cnum, dev, inode, token);
1672 }
1673
1674 /****************************************************************************
1675 seek a file. Try to avoid the seek if possible
1676 ****************************************************************************/
1677 int seek_file(int fnum,int pos)
1678 {
1679   int offset = 0;
1680   if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1681     offset = 3;
1682
1683   Files[fnum].pos = lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - offset;
1684   return(Files[fnum].pos);
1685 }
1686
1687 /****************************************************************************
1688 read from a file
1689 ****************************************************************************/
1690 int read_file(int fnum,char *data,int pos,int n)
1691 {
1692   int ret=0,readret;
1693
1694   if (!Files[fnum].can_write)
1695     {
1696       ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1697
1698       data += ret;
1699       n -= ret;
1700       pos += ret;
1701     }
1702
1703 #if USE_MMAP
1704   if (Files[fnum].mmap_ptr)
1705     {
1706       int num = MIN(n,Files[fnum].mmap_size-pos);
1707       if (num > 0)
1708         {
1709           memcpy(data,Files[fnum].mmap_ptr+pos,num);
1710           data += num;
1711           pos += num;
1712           n -= num;
1713           ret += num;
1714         }
1715     }
1716 #endif
1717
1718   if (n <= 0)
1719     return(ret);
1720
1721   if (seek_file(fnum,pos) != pos)
1722     {
1723       DEBUG(3,("Failed to seek to %d\n",pos));
1724       return(ret);
1725     }
1726   
1727   if (n > 0) {
1728     readret = read(Files[fnum].fd_ptr->fd,data,n);
1729     if (readret > 0) ret += readret;
1730   }
1731
1732   return(ret);
1733 }
1734
1735
1736 /****************************************************************************
1737 write to a file
1738 ****************************************************************************/
1739 int write_file(int fnum,char *data,int n)
1740 {
1741   if (!Files[fnum].can_write) {
1742     errno = EPERM;
1743     return(0);
1744   }
1745
1746   if (!Files[fnum].modified) {
1747     struct stat st;
1748     Files[fnum].modified = True;
1749     if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1750       int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1751       if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {  
1752         dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1753       }
1754     }  
1755   }
1756
1757   return(write_data(Files[fnum].fd_ptr->fd,data,n));
1758 }
1759
1760
1761 /****************************************************************************
1762 load parameters specific to a connection/service
1763 ****************************************************************************/
1764 BOOL become_service(int cnum,BOOL do_chdir)
1765 {
1766   extern char magic_char;
1767   static int last_cnum = -1;
1768   int snum;
1769
1770   if (!OPEN_CNUM(cnum))
1771     {
1772       last_cnum = -1;
1773       return(False);
1774     }
1775
1776   Connections[cnum].lastused = smb_last_time;
1777
1778   snum = SNUM(cnum);
1779   
1780   if (do_chdir &&
1781       ChDir(Connections[cnum].connectpath) != 0 &&
1782       ChDir(Connections[cnum].origpath) != 0)
1783     {
1784       DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1785             Connections[cnum].connectpath,cnum));     
1786       return(False);
1787     }
1788
1789   if (cnum == last_cnum)
1790     return(True);
1791
1792   last_cnum = cnum;
1793
1794   case_default = lp_defaultcase(snum);
1795   case_preserve = lp_preservecase(snum);
1796   short_case_preserve = lp_shortpreservecase(snum);
1797   case_mangle = lp_casemangle(snum);
1798   case_sensitive = lp_casesensitive(snum);
1799   magic_char = lp_magicchar(snum);
1800   use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1801   return(True);
1802 }
1803
1804
1805 /****************************************************************************
1806   find a service entry
1807 ****************************************************************************/
1808 int find_service(char *service)
1809 {
1810    int iService;
1811
1812    string_sub(service,"\\","/");
1813
1814    iService = lp_servicenumber(service);
1815
1816    /* now handle the special case of a home directory */
1817    if (iService < 0)
1818    {
1819       char *phome_dir = get_home_dir(service);
1820       DEBUG(3,("checking for home directory %s gave %s\n",service,
1821             phome_dir?phome_dir:"(NULL)"));
1822       if (phome_dir)
1823       {   
1824          int iHomeService;
1825          if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
1826          {
1827             lp_add_home(service,iHomeService,phome_dir);
1828             iService = lp_servicenumber(service);
1829          }
1830       }
1831    }
1832
1833    /* If we still don't have a service, attempt to add it as a printer. */
1834    if (iService < 0)
1835    {
1836       int iPrinterService;
1837
1838       if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
1839       {
1840          char *pszTemp;
1841
1842          DEBUG(3,("checking whether %s is a valid printer name...\n", service));
1843          pszTemp = PRINTCAP;
1844          if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
1845          {
1846             DEBUG(3,("%s is a valid printer name\n", service));
1847             DEBUG(3,("adding %s as a printer service\n", service));
1848             lp_add_printer(service,iPrinterService);
1849             iService = lp_servicenumber(service);
1850             if (iService < 0)
1851                DEBUG(0,("failed to add %s as a printer service!\n", service));
1852          }
1853          else
1854             DEBUG(3,("%s is not a valid printer name\n", service));
1855       }
1856    }
1857
1858    /* just possibly it's a default service? */
1859    if (iService < 0) 
1860      {
1861        char *defservice = lp_defaultservice();
1862        if (defservice && *defservice && !strequal(defservice,service)) {
1863          iService = find_service(defservice);
1864          if (iService >= 0) {
1865            string_sub(service,"_","/");
1866            iService = lp_add_service(service,iService);
1867          }
1868        }
1869      }
1870
1871    if (iService >= 0)
1872       if (!VALID_SNUM(iService))
1873       {
1874          DEBUG(0,("Invalid snum %d for %s\n",iService,service));
1875          iService = -1;
1876       }
1877
1878    if (iService < 0)
1879       DEBUG(3,("find_service() failed to find service %s\n", service));
1880
1881    return (iService);
1882 }
1883
1884
1885 /****************************************************************************
1886   create an error packet from a cached error.
1887 ****************************************************************************/
1888 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
1889 {
1890   write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
1891
1892   int32 eclass = wbmpx->wr_errclass;
1893   int32 err = wbmpx->wr_error;
1894
1895   /* We can now delete the auxiliary struct */
1896   free((char *)wbmpx);
1897   Files[fnum].wbmpx_ptr = NULL;
1898   return error_packet(inbuf,outbuf,eclass,err,line);
1899 }
1900
1901
1902 struct
1903 {
1904   int unixerror;
1905   int smbclass;
1906   int smbcode;
1907 } unix_smb_errmap[] =
1908 {
1909   {EPERM,ERRDOS,ERRnoaccess},
1910   {EACCES,ERRDOS,ERRnoaccess},
1911   {ENOENT,ERRDOS,ERRbadfile},
1912   {EIO,ERRHRD,ERRgeneral},
1913   {EBADF,ERRSRV,ERRsrverror},
1914   {EINVAL,ERRSRV,ERRsrverror},
1915   {EEXIST,ERRDOS,ERRfilexists},
1916   {ENFILE,ERRDOS,ERRnofids},
1917   {EMFILE,ERRDOS,ERRnofids},
1918   {ENOSPC,ERRHRD,ERRdiskfull},
1919 #ifdef EDQUOT
1920   {EDQUOT,ERRHRD,ERRdiskfull},
1921 #endif
1922 #ifdef ENOTEMPTY
1923   {ENOTEMPTY,ERRDOS,ERRnoaccess},
1924 #endif
1925 #ifdef EXDEV
1926   {EXDEV,ERRDOS,ERRdiffdevice},
1927 #endif
1928   {EROFS,ERRHRD,ERRnowrite},
1929   {0,0,0}
1930 };
1931
1932
1933 /****************************************************************************
1934   create an error packet from errno
1935 ****************************************************************************/
1936 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
1937 {
1938   int eclass=def_class;
1939   int ecode=def_code;
1940   int i=0;
1941
1942   if (unix_ERR_class != SUCCESS)
1943     {
1944       eclass = unix_ERR_class;
1945       ecode = unix_ERR_code;
1946       unix_ERR_class = SUCCESS;
1947       unix_ERR_code = 0;
1948     }
1949   else
1950     {
1951       while (unix_smb_errmap[i].smbclass != 0)
1952         {
1953           if (unix_smb_errmap[i].unixerror == errno)
1954             {
1955               eclass = unix_smb_errmap[i].smbclass;
1956               ecode = unix_smb_errmap[i].smbcode;
1957               break;
1958             }
1959           i++;
1960         }
1961     }
1962
1963   return(error_packet(inbuf,outbuf,eclass,ecode,line));
1964 }
1965
1966
1967 /****************************************************************************
1968   create an error packet. Normally called using the ERROR() macro
1969 ****************************************************************************/
1970 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
1971 {
1972   int outsize = set_message(outbuf,0,0,True);
1973   int cmd;
1974   cmd = CVAL(inbuf,smb_com);
1975   
1976   CVAL(outbuf,smb_rcls) = error_class;
1977   SSVAL(outbuf,smb_err,error_code);  
1978   
1979   DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
1980            timestring(),
1981            line,
1982            (int)CVAL(inbuf,smb_com),
1983            smb_fn_name(CVAL(inbuf,smb_com)),
1984            error_class,
1985            error_code));
1986
1987   if (errno != 0)
1988     DEBUG(3,("error string = %s\n",strerror(errno)));
1989   
1990   return(outsize);
1991 }
1992
1993
1994 #ifndef SIGCLD_IGNORE
1995 /****************************************************************************
1996 this prevents zombie child processes
1997 ****************************************************************************/
1998 static int sig_cld()
1999 {
2000   static int depth = 0;
2001   if (depth != 0)
2002     {
2003       DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2004       depth=0;
2005       return(0);
2006     }
2007   depth++;
2008
2009   BlockSignals(True,SIGCLD);
2010   DEBUG(5,("got SIGCLD\n"));
2011
2012 #ifdef USE_WAITPID
2013   while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2014 #endif
2015
2016   /* Stop zombies */
2017   /* Stevens, Adv. Unix Prog. says that on system V you must call
2018      wait before reinstalling the signal handler, because the kernel
2019      calls the handler from within the signal-call when there is a
2020      child that has exited. This would lead to an infinite recursion
2021      if done vice versa. */
2022         
2023 #ifndef DONT_REINSTALL_SIG
2024 #ifdef SIGCLD_IGNORE
2025   signal(SIGCLD, SIG_IGN);  
2026 #else
2027   signal(SIGCLD, SIGNAL_CAST sig_cld);
2028 #endif
2029 #endif
2030
2031 #ifndef USE_WAITPID
2032   while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
2033 #endif
2034   depth--;
2035   BlockSignals(False,SIGCLD);
2036   return 0;
2037 }
2038 #endif
2039
2040 /****************************************************************************
2041   this is called when the client exits abruptly
2042   **************************************************************************/
2043 static int sig_pipe()
2044 {
2045   extern int password_client;
2046   BlockSignals(True,SIGPIPE);
2047
2048   if (password_client != -1) {
2049     DEBUG(3,("lost connection to password server\n"));
2050     close(password_client);
2051     password_client = -1;
2052 #ifndef DONT_REINSTALL_SIG
2053     signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2054 #endif
2055     BlockSignals(False,SIGPIPE);
2056     return 0;
2057   }
2058
2059   exit_server("Got sigpipe\n");
2060   return(0);
2061 }
2062
2063 /****************************************************************************
2064   open the socket communication
2065 ****************************************************************************/
2066 static BOOL open_sockets(BOOL is_daemon,int port)
2067 {
2068   extern int Client;
2069
2070   if (is_daemon)
2071     {
2072       int s;
2073       struct sockaddr addr;
2074       int in_addrlen = sizeof(addr);
2075        
2076       /* Stop zombies */
2077 #ifdef SIGCLD_IGNORE
2078       signal(SIGCLD, SIG_IGN);
2079 #else
2080       signal(SIGCLD, SIGNAL_CAST sig_cld);
2081 #endif
2082
2083       /* open an incoming socket */
2084       s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
2085       if (s == -1)
2086         return(False);
2087
2088       /* ready to listen */
2089       if (listen(s, 5) == -1) 
2090         {
2091           DEBUG(0,("listen: %s",strerror(errno)));
2092           close(s);
2093           return False;
2094         }
2095       
2096       if(atexit_set == 0)
2097         atexit(killkids);
2098
2099       /* now accept incoming connections - forking a new process
2100          for each incoming connection */
2101       DEBUG(2,("waiting for a connection\n"));
2102       while (1)
2103         {
2104           Client = accept(s,&addr,&in_addrlen);
2105
2106           if (Client == -1 && errno == EINTR)
2107             continue;
2108
2109           if (Client == -1)
2110             {
2111               DEBUG(0,("accept: %s",strerror(errno)));
2112               continue;
2113             }
2114
2115 #ifdef NO_FORK_DEBUG
2116 #ifndef NO_SIGNAL_TEST
2117           signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2118           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2119 #endif
2120           return True;
2121 #else
2122           if (Client != -1 && fork()==0)
2123             {
2124               /* Child code ... */
2125 #ifndef NO_SIGNAL_TEST
2126               signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2127               signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2128 #endif
2129               /* close the listening socket */
2130               close(s);
2131
2132               /* close our standard file descriptors */
2133               close_low_fds();
2134               am_parent = 0;
2135   
2136               set_socket_options(Client,"SO_KEEPALIVE");
2137               set_socket_options(Client,user_socket_options);
2138
2139               /* Reset global variables in util.c so that
2140                  client substitutions will be done correctly
2141                  in the process.
2142                */
2143               reset_globals_after_fork();
2144               return True; 
2145             }
2146           close(Client); /* The parent doesn't need this socket */
2147 #endif
2148         }
2149     }
2150   else
2151     {
2152       /* We will abort gracefully when the client or remote system 
2153          goes away */
2154 #ifndef NO_SIGNAL_TEST
2155       signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2156 #endif
2157       Client = dup(0);
2158
2159       /* close our standard file descriptors */
2160       close_low_fds();
2161
2162       set_socket_options(Client,"SO_KEEPALIVE");
2163       set_socket_options(Client,user_socket_options);
2164     }
2165
2166   return True;
2167 }
2168
2169
2170 /****************************************************************************
2171 check if a snum is in use
2172 ****************************************************************************/
2173 BOOL snum_used(int snum)
2174 {
2175   int i;
2176   for (i=0;i<MAX_CONNECTIONS;i++)
2177     if (OPEN_CNUM(i) && (SNUM(i) == snum))
2178       return(True);
2179   return(False);
2180 }
2181
2182 /****************************************************************************
2183   reload the services file
2184   **************************************************************************/
2185 BOOL reload_services(BOOL test)
2186 {
2187   BOOL ret;
2188
2189   if (lp_loaded())
2190     {
2191       pstring fname;
2192       strcpy(fname,lp_configfile());
2193       if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2194         {
2195           strcpy(servicesf,fname);
2196           test = False;
2197         }
2198     }
2199
2200   reopen_logs();
2201
2202   if (test && !lp_file_list_changed())
2203     return(True);
2204
2205   lp_killunused(snum_used);
2206
2207   ret = lp_load(servicesf,False);
2208
2209   /* perhaps the config filename is now set */
2210   if (!test)
2211     reload_services(True);
2212
2213   reopen_logs();
2214
2215   load_interfaces();
2216
2217   {
2218     extern int Client;
2219     if (Client != -1) {      
2220       set_socket_options(Client,"SO_KEEPALIVE");
2221       set_socket_options(Client,user_socket_options);
2222     }
2223   }
2224
2225   create_mangled_stack(lp_mangledstack());
2226
2227   /* this forces service parameters to be flushed */
2228   become_service(-1,True);
2229
2230   return(ret);
2231 }
2232
2233
2234
2235 /****************************************************************************
2236 this prevents zombie child processes
2237 ****************************************************************************/
2238 static int sig_hup()
2239 {
2240   BlockSignals(True,SIGHUP);
2241   DEBUG(0,("Got SIGHUP\n"));
2242   reload_services(False);
2243 #ifndef DONT_REINSTALL_SIG
2244   signal(SIGHUP,SIGNAL_CAST sig_hup);
2245 #endif
2246   BlockSignals(False,SIGHUP);
2247   return(0);
2248 }
2249
2250 /****************************************************************************
2251 Setup the groups a user belongs to.
2252 ****************************************************************************/
2253 int setup_groups(char *user, int uid, int gid, int *p_ngroups, 
2254                  int **p_igroups, gid_t **p_groups)
2255 {
2256   if (-1 == initgroups(user,gid))
2257     {
2258       if (getuid() == 0)
2259         {
2260           DEBUG(0,("Unable to initgroups!\n"));
2261           if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2262             DEBUG(0,("This is probably a problem with the account %s\n",user));
2263         }
2264     }
2265   else
2266     {
2267       int i,ngroups;
2268       int *igroups;
2269       gid_t grp = 0;
2270       ngroups = getgroups(0,&grp);
2271       if (ngroups <= 0)
2272         ngroups = 32;
2273       igroups = (int *)malloc(sizeof(int)*ngroups);
2274       for (i=0;i<ngroups;i++)
2275         igroups[i] = 0x42424242;
2276       ngroups = getgroups(ngroups,(gid_t *)igroups);
2277
2278       if (igroups[0] == 0x42424242)
2279         ngroups = 0;
2280
2281       *p_ngroups = ngroups;
2282
2283       /* The following bit of code is very strange. It is due to the
2284          fact that some OSes use int* and some use gid_t* for
2285          getgroups, and some (like SunOS) use both, one in prototypes,
2286          and one in man pages and the actual code. Thus we detect it
2287          dynamically using some very ugly code */
2288       if (ngroups > 0)
2289         {
2290           /* does getgroups return ints or gid_t ?? */
2291           static BOOL groups_use_ints = True;
2292
2293           if (groups_use_ints && 
2294               ngroups == 1 && 
2295               SVAL(igroups,2) == 0x4242)
2296             groups_use_ints = False;
2297           
2298           for (i=0;groups_use_ints && i<ngroups;i++)
2299             if (igroups[i] == 0x42424242)
2300               groups_use_ints = False;
2301               
2302           if (groups_use_ints)
2303             {
2304               *p_igroups = igroups;
2305               *p_groups = (gid_t *)igroups;       
2306             }
2307           else
2308             {
2309               gid_t *groups = (gid_t *)igroups;
2310               igroups = (int *)malloc(sizeof(int)*ngroups);
2311               for (i=0;i<ngroups;i++)
2312                 igroups[i] = groups[i];
2313               *p_igroups = igroups;
2314               *p_groups = (gid_t *)groups;
2315             }
2316         }
2317       DEBUG(3,("%s is in %d groups\n",user,ngroups));
2318       for (i=0;i<ngroups;i++)
2319         DEBUG(3,("%d ",igroups[i]));
2320       DEBUG(3,("\n"));
2321     }
2322   return 0;
2323 }
2324
2325 /****************************************************************************
2326   make a connection to a service
2327 ****************************************************************************/
2328 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
2329 {
2330   int cnum;
2331   int snum;
2332   struct passwd *pass = NULL;
2333   connection_struct *pcon;
2334   BOOL guest = False;
2335   BOOL force = False;
2336   static BOOL first_connection = True;
2337
2338   strlower(service);
2339
2340   snum = find_service(service);
2341   if (snum < 0)
2342     {
2343       if (strequal(service,"IPC$"))
2344         {         
2345           DEBUG(3,("%s refusing IPC connection\n",timestring()));
2346           return(-3);
2347         }
2348
2349       DEBUG(0,("%s couldn't find service %s\n",timestring(),service));      
2350       return(-2);
2351     }
2352
2353   if (strequal(service,HOMES_NAME))
2354     {
2355       if (*user && Get_Pwnam(user,True))
2356         return(make_connection(user,user,password,pwlen,dev,vuid));
2357
2358       if (validated_username(vuid))
2359         {
2360           strcpy(user,validated_username(vuid));
2361           return(make_connection(user,user,password,pwlen,dev,vuid));
2362         }
2363     }
2364
2365   if (!lp_snum_ok(snum) || !check_access(snum)) {    
2366     return(-4);
2367   }
2368
2369   /* you can only connect to the IPC$ service as an ipc device */
2370   if (strequal(service,"IPC$"))
2371     strcpy(dev,"IPC");
2372
2373   if (*dev == '?' || !*dev)
2374     {
2375       if (lp_print_ok(snum))
2376         strcpy(dev,"LPT1:");
2377       else
2378         strcpy(dev,"A:");
2379     }
2380
2381   /* if the request is as a printer and you can't print then refuse */
2382   strupper(dev);
2383   if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
2384     DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
2385     return(-6);
2386   }
2387
2388   /* lowercase the user name */
2389   strlower(user);
2390
2391   /* add it as a possible user name */
2392   add_session_user(service);
2393
2394   /* shall we let them in? */
2395   if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
2396     {
2397       DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
2398       return(-1);
2399     }
2400   
2401   cnum = find_free_connection(str_checksum(service) + str_checksum(user));
2402   if (cnum < 0)
2403     {
2404       DEBUG(0,("%s couldn't find free connection\n",timestring()));      
2405       return(-1);
2406     }
2407
2408   pcon = &Connections[cnum];
2409   bzero((char *)pcon,sizeof(*pcon));
2410
2411   /* find out some info about the user */
2412   pass = Get_Pwnam(user,True);
2413
2414   if (pass == NULL)
2415     {
2416       DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); 
2417       return(-7);
2418     }
2419
2420   pcon->read_only = lp_readonly(snum);
2421
2422   {
2423     pstring list;
2424     StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
2425     string_sub(list,"%S",service);
2426
2427     if (user_in_list(user,list))
2428       pcon->read_only = True;
2429
2430     StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
2431     string_sub(list,"%S",service);
2432
2433     if (user_in_list(user,list))
2434       pcon->read_only = False;    
2435   }
2436
2437   /* admin user check */
2438   if (user_in_list(user,lp_admin_users(snum)) &&
2439       !pcon->read_only)
2440     {
2441       pcon->admin_user = True;
2442       DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
2443     }
2444   else
2445     pcon->admin_user = False;
2446     
2447   pcon->force_user = force;
2448   pcon->vuid = vuid;
2449   pcon->uid = pass->pw_uid;
2450   pcon->gid = pass->pw_gid;
2451   pcon->num_files_open = 0;
2452   pcon->lastused = time(NULL);
2453   pcon->service = snum;
2454   pcon->used = True;
2455   pcon->printer = (strncmp(dev,"LPT",3) == 0);
2456   pcon->ipc = (strncmp(dev,"IPC",3) == 0);
2457   pcon->dirptr = NULL;
2458   string_set(&pcon->dirpath,"");
2459   string_set(&pcon->user,user);
2460
2461 #if HAVE_GETGRNAM 
2462   if (*lp_force_group(snum))
2463     {
2464       struct group *gptr;
2465       pstring gname;
2466
2467       StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
2468       /* default service may be a group name            */
2469       string_sub(gname,"%S",service);
2470       gptr = (struct group *)getgrnam(gname);
2471
2472       if (gptr)
2473         {
2474           pcon->gid = gptr->gr_gid;
2475           DEBUG(3,("Forced group %s\n",gname));
2476         }
2477       else
2478         DEBUG(1,("Couldn't find group %s\n",gname));
2479     }
2480 #endif
2481
2482   if (*lp_force_user(snum))
2483     {
2484       struct passwd *pass2;
2485       fstring fuser;
2486       strcpy(fuser,lp_force_user(snum));
2487       pass2 = (struct passwd *)Get_Pwnam(fuser,True);
2488       if (pass2)
2489         {
2490           pcon->uid = pass2->pw_uid;
2491           string_set(&pcon->user,fuser);
2492           strcpy(user,fuser);
2493           pcon->force_user = True;
2494           DEBUG(3,("Forced user %s\n",fuser));    
2495         }
2496       else
2497         DEBUG(1,("Couldn't find user %s\n",fuser));
2498     }
2499
2500   {
2501     pstring s;
2502     strcpy(s,lp_pathname(snum));
2503     standard_sub(cnum,s);
2504     string_set(&pcon->connectpath,s);
2505     DEBUG(3,("Connect path is %s\n",s));
2506   }
2507
2508   /* groups stuff added by ih */
2509   pcon->ngroups = 0;
2510   pcon->groups = NULL;
2511
2512   if (!IS_IPC(cnum))
2513     {
2514       /* Find all the groups this uid is in and store them. Used by become_user() */
2515       setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
2516       
2517       /* check number of connections */
2518       if (!claim_connection(cnum,
2519                             lp_servicename(SNUM(cnum)),
2520                             lp_max_connections(SNUM(cnum)),False))
2521         {
2522           DEBUG(1,("too many connections - rejected\n"));
2523           return(-8);
2524         }  
2525
2526       if (lp_status(SNUM(cnum)))
2527         claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
2528
2529       first_connection = False;
2530     } /* IS_IPC */
2531
2532   pcon->open = True;
2533
2534   /* execute any "root preexec = " line */
2535   if (*lp_rootpreexec(SNUM(cnum)))
2536     {
2537       pstring cmd;
2538       strcpy(cmd,lp_rootpreexec(SNUM(cnum)));
2539       standard_sub(cnum,cmd);
2540       DEBUG(5,("cmd=%s\n",cmd));
2541       smbrun(cmd,NULL,False);
2542     }
2543
2544   if (!become_user(cnum,pcon->vuid))
2545     {
2546       DEBUG(0,("Can't become connected user!\n"));
2547       pcon->open = False;
2548       if (!IS_IPC(cnum)) {
2549         yield_connection(cnum,
2550                          lp_servicename(SNUM(cnum)),
2551                          lp_max_connections(SNUM(cnum)));
2552         if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2553       }
2554       return(-1);
2555     }
2556
2557   if (ChDir(pcon->connectpath) != 0)
2558     {
2559       DEBUG(0,("Can't change directory to %s (%s)\n",
2560                pcon->connectpath,strerror(errno)));
2561       pcon->open = False;
2562       unbecome_user();
2563       if (!IS_IPC(cnum)) {
2564         yield_connection(cnum,
2565                          lp_servicename(SNUM(cnum)),
2566                          lp_max_connections(SNUM(cnum)));
2567         if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
2568       }
2569       return(-5);      
2570     }
2571
2572   string_set(&pcon->origpath,pcon->connectpath);
2573
2574 #if SOFTLINK_OPTIMISATION
2575   /* resolve any soft links early */
2576   {
2577     pstring s;
2578     strcpy(s,pcon->connectpath);
2579     GetWd(s);
2580     string_set(&pcon->connectpath,s);
2581     ChDir(pcon->connectpath);
2582   }
2583 #endif
2584
2585   num_connections_open++;
2586   add_session_user(user);
2587   
2588   /* execute any "preexec = " line */
2589   if (*lp_preexec(SNUM(cnum)))
2590     {
2591       pstring cmd;
2592       strcpy(cmd,lp_preexec(SNUM(cnum)));
2593       standard_sub(cnum,cmd);
2594       smbrun(cmd,NULL,False);
2595     }
2596   
2597   /* we've finished with the sensitive stuff */
2598   unbecome_user();
2599
2600   {
2601     DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
2602                             timestring(),
2603                             remote_machine,
2604                             client_addr(),
2605                             lp_servicename(SNUM(cnum)),user,
2606                             pcon->uid,
2607                             pcon->gid,
2608                             (int)getpid()));
2609   }
2610
2611   return(cnum);
2612 }
2613
2614
2615 /****************************************************************************
2616   find first available file slot
2617 ****************************************************************************/
2618 int find_free_file(void )
2619 {
2620   int i;
2621   /* we start at 1 here for an obscure reason I can't now remember,
2622      but I think is important :-) */
2623   for (i=1;i<MAX_OPEN_FILES;i++)
2624     if (!Files[i].open)
2625       return(i);
2626   DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
2627   return(-1);
2628 }
2629
2630 /****************************************************************************
2631   find first available connection slot, starting from a random position.
2632 The randomisation stops problems with the server dieing and clients
2633 thinking the server is still available.
2634 ****************************************************************************/
2635 static int find_free_connection(int hash )
2636 {
2637   int i;
2638   BOOL used=False;
2639   hash = (hash % (MAX_CONNECTIONS-2))+1;
2640
2641  again:
2642
2643   for (i=hash+1;i!=hash;)
2644     {
2645       if (!Connections[i].open && Connections[i].used == used) 
2646         {
2647           DEBUG(3,("found free connection number %d\n",i));
2648           return(i);
2649         }
2650       i++;
2651       if (i == MAX_CONNECTIONS)
2652         i = 1;
2653     }
2654
2655   if (!used)
2656     {
2657       used = !used;
2658       goto again;
2659     }
2660
2661   DEBUG(1,("ERROR! Out of connection structures\n"));
2662   return(-1);
2663 }
2664
2665
2666 /****************************************************************************
2667 reply for the core protocol
2668 ****************************************************************************/
2669 int reply_corep(char *outbuf)
2670 {
2671   int outsize = set_message(outbuf,1,0,True);
2672
2673   Protocol = PROTOCOL_CORE;
2674
2675   return outsize;
2676 }
2677
2678
2679 /****************************************************************************
2680 reply for the coreplus protocol
2681 ****************************************************************************/
2682 int reply_coreplus(char *outbuf)
2683 {
2684   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2685   int outsize = set_message(outbuf,13,0,True);
2686   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2687                                  readbraw and writebraw (possibly) */
2688   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2689   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */  
2690
2691   Protocol = PROTOCOL_COREPLUS;
2692
2693   return outsize;
2694 }
2695
2696
2697 /****************************************************************************
2698 reply for the lanman 1.0 protocol
2699 ****************************************************************************/
2700 int reply_lanman1(char *outbuf)
2701 {
2702   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2703   int secword=0;
2704   BOOL doencrypt = SMBENCRYPT();
2705   time_t t = time(NULL);
2706   /* We need to save and restore this as it can be destroyed
2707      if we call another server if security=server
2708      Thanks to Paul Nelson @ Thursby for pointing this out.
2709    */
2710   uint16 mid = SVAL(outbuf, smb_mid);
2711
2712   if (lp_security()>=SEC_USER) secword |= 1;
2713   if (doencrypt) secword |= 2;
2714
2715   set_message(outbuf,13,doencrypt?8:0,True);
2716   SSVAL(outbuf,smb_vwv1,secword); 
2717 #ifdef SMB_PASSWD
2718   /* Create a token value and add it to the outgoing packet. */
2719   if (doencrypt) 
2720     generate_next_challenge(smb_buf(outbuf));
2721 #endif
2722
2723   Protocol = PROTOCOL_LANMAN1;
2724
2725   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2726     DEBUG(3,("using password server validation\n"));
2727 #ifdef SMB_PASSWD
2728   if (doencrypt) set_challenge(smb_buf(outbuf));    
2729 #endif
2730   }
2731
2732   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2733   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2734   SSVAL(outbuf,smb_vwv2,max_recv);
2735   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
2736   SSVAL(outbuf,smb_vwv4,1);
2737   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
2738                                  readbraw writebraw (possibly) */
2739   SIVAL(outbuf,smb_vwv6,getpid());
2740   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2741
2742   put_dos_date(outbuf,smb_vwv8,t);
2743
2744   return (smb_len(outbuf)+4);
2745 }
2746
2747
2748 /****************************************************************************
2749 reply for the lanman 2.0 protocol
2750 ****************************************************************************/
2751 int reply_lanman2(char *outbuf)
2752 {
2753   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
2754   int secword=0;
2755   BOOL doencrypt = SMBENCRYPT();
2756   time_t t = time(NULL);
2757   /* We need to save and restore this as it can be destroyed
2758      if we call another server if security=server
2759      Thanks to Paul Nelson @ Thursby for pointing this out.
2760    */
2761   uint16 mid = SVAL(outbuf, smb_mid);
2762
2763   if (lp_security()>=SEC_USER) secword |= 1;
2764   if (doencrypt) secword |= 2;
2765
2766   set_message(outbuf,13,doencrypt?8:0,True);
2767   SSVAL(outbuf,smb_vwv1,secword); 
2768 #ifdef SMB_PASSWD
2769   /* Create a token value and add it to the outgoing packet. */
2770   if (doencrypt) 
2771     generate_next_challenge(smb_buf(outbuf));
2772 #endif
2773
2774   SIVAL(outbuf,smb_vwv6,getpid());
2775
2776   Protocol = PROTOCOL_LANMAN2;
2777
2778   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2779     DEBUG(3,("using password server validation\n"));
2780 #ifdef SMB_PASSWD
2781     if (doencrypt) set_challenge(smb_buf(outbuf));    
2782 #endif
2783   }
2784
2785   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
2786   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2787   SSVAL(outbuf,smb_vwv2,max_recv);
2788   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
2789   SSVAL(outbuf,smb_vwv4,1);
2790   SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
2791   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
2792   put_dos_date(outbuf,smb_vwv8,t);
2793
2794   return (smb_len(outbuf)+4);
2795 }
2796
2797
2798 /****************************************************************************
2799 reply for the nt protocol
2800 ****************************************************************************/
2801 int reply_nt1(char *outbuf)
2802 {
2803   /* dual names + lock_and_read + nt SMBs + remote API calls */
2804   int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
2805 /*
2806   other valid capabilities which we may support at some time...
2807                      CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
2808                      CAP_LARGE_FILES|CAP_LARGE_READX|
2809                      CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
2810  */
2811
2812   int secword=0;
2813   BOOL doencrypt = SMBENCRYPT();
2814   time_t t = time(NULL);
2815   int data_len;
2816   int encrypt_len;
2817   char challenge_len = 8;
2818   /* We need to save and restore this as it can be destroyed
2819      if we call another server if security=server
2820      Thanks to Paul Nelson @ Thursby for pointing this out.
2821    */
2822   uint16 mid = SVAL(outbuf, smb_mid);
2823
2824   if (lp_readraw() && lp_writeraw())
2825   {
2826     capabilities |= CAP_RAW_MODE;
2827   }
2828
2829   if (lp_security()>=SEC_USER) secword |= 1;
2830   if (doencrypt) secword |= 2;
2831
2832   /* decide where (if) to put the encryption challenge, and
2833      follow it with the OEM'd domain name
2834    */
2835   encrypt_len = doencrypt?challenge_len:0;
2836 #if UNICODE
2837   data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
2838 #else
2839   data_len = encrypt_len + strlen(myworkgroup) + 1;
2840 #endif
2841
2842   set_message(outbuf,17,data_len,True);
2843
2844 #if UNICODE
2845   /* put the OEM'd domain name */
2846   PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
2847 #else
2848   strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
2849 #endif
2850
2851   CVAL(outbuf,smb_vwv1) = secword;
2852 #ifdef SMB_PASSWD
2853   /* Create a token value and add it to the outgoing packet. */
2854   if (doencrypt)
2855   {
2856     generate_next_challenge(smb_buf(outbuf));
2857
2858     /* Tell the nt machine how long the challenge is. */
2859     SSVALS(outbuf,smb_vwv16+1,challenge_len);
2860   }
2861 #endif
2862
2863   Protocol = PROTOCOL_NT1;
2864
2865   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
2866     DEBUG(3,("using password server validation\n"));
2867 #ifdef SMB_PASSWD
2868     if (doencrypt) set_challenge(smb_buf(outbuf));    
2869 #endif
2870   }
2871
2872   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
2873   SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
2874   SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
2875   SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
2876   SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
2877   SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
2878   SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
2879   put_long_date(outbuf+smb_vwv11+1,t);
2880   SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
2881   SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
2882
2883   return (smb_len(outbuf)+4);
2884 }
2885
2886 /* these are the protocol lists used for auto architecture detection:
2887
2888 WinNT 3.51:
2889 protocol [PC NETWORK PROGRAM 1.0]
2890 protocol [XENIX CORE]
2891 protocol [MICROSOFT NETWORKS 1.03]
2892 protocol [LANMAN1.0]
2893 protocol [Windows for Workgroups 3.1a]
2894 protocol [LM1.2X002]
2895 protocol [LANMAN2.1]
2896 protocol [NT LM 0.12]
2897
2898 Win95:
2899 protocol [PC NETWORK PROGRAM 1.0]
2900 protocol [XENIX CORE]
2901 protocol [MICROSOFT NETWORKS 1.03]
2902 protocol [LANMAN1.0]
2903 protocol [Windows for Workgroups 3.1a]
2904 protocol [LM1.2X002]
2905 protocol [LANMAN2.1]
2906 protocol [NT LM 0.12]
2907
2908 OS/2:
2909 protocol [PC NETWORK PROGRAM 1.0]
2910 protocol [XENIX CORE]
2911 protocol [LANMAN1.0]
2912 protocol [LM1.2X002]
2913 protocol [LANMAN2.1]
2914 */
2915
2916 /*
2917   * Modified to recognize the architecture of the remote machine better.
2918   *
2919   * This appears to be the matrix of which protocol is used by which
2920   * MS product.
2921        Protocol                       WfWg    Win95   WinNT  OS/2
2922        PC NETWORK PROGRAM 1.0          1       1       1      1
2923        XENIX CORE                                      2      2
2924        MICROSOFT NETWORKS 3.0          2       2       
2925        DOS LM1.2X002                   3       3       
2926        MICROSOFT NETWORKS 1.03                         3
2927        DOS LANMAN2.1                   4       4       
2928        LANMAN1.0                                       4      3
2929        Windows for Workgroups 3.1a     5       5       5
2930        LM1.2X002                                       6      4
2931        LANMAN2.1                                       7      5
2932        NT LM 0.12                              6       8
2933   *
2934   *  tim@fsg.com 09/29/95
2935   */
2936   
2937 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
2938 #define ARCH_WIN95    0x2
2939 #define ARCH_OS2      0xC      /* Again OS/2 is like NT */
2940 #define ARCH_WINNT    0x8
2941 #define ARCH_SAMBA    0x10
2942  
2943 #define ARCH_ALL      0x1F
2944  
2945 /* List of supported protocols, most desired first */
2946 struct {
2947   char *proto_name;
2948   char *short_name;
2949   int (*proto_reply_fn)(char *);
2950   int protocol_level;
2951 } supported_protocols[] = {
2952   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
2953   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
2954   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2955   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2956   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
2957   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
2958   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
2959   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
2960   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
2961   {NULL,NULL},
2962 };
2963
2964
2965 /****************************************************************************
2966   reply to a negprot
2967 ****************************************************************************/
2968 static int reply_negprot(char *inbuf,char *outbuf)
2969 {
2970   extern fstring remote_arch;
2971   int outsize = set_message(outbuf,1,0,True);
2972   int Index=0;
2973   int choice= -1;
2974   int protocol;
2975   char *p;
2976   int bcc = SVAL(smb_buf(inbuf),-2);
2977   int arch = ARCH_ALL;
2978
2979   p = smb_buf(inbuf)+1;
2980   while (p < (smb_buf(inbuf) + bcc))
2981     { 
2982       Index++;
2983       DEBUG(3,("Requested protocol [%s]\n",p));
2984       if (strcsequal(p,"Windows for Workgroups 3.1a"))
2985         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
2986       else if (strcsequal(p,"DOS LM1.2X002"))
2987         arch &= ( ARCH_WFWG | ARCH_WIN95 );
2988       else if (strcsequal(p,"DOS LANMAN2.1"))
2989         arch &= ( ARCH_WFWG | ARCH_WIN95 );
2990       else if (strcsequal(p,"NT LM 0.12"))
2991         arch &= ( ARCH_WIN95 | ARCH_WINNT );
2992       else if (strcsequal(p,"LANMAN2.1"))
2993         arch &= ( ARCH_WINNT | ARCH_OS2 );
2994       else if (strcsequal(p,"LM1.2X002"))
2995         arch &= ( ARCH_WINNT | ARCH_OS2 );
2996       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
2997         arch &= ARCH_WINNT;
2998       else if (strcsequal(p,"XENIX CORE"))
2999         arch &= ( ARCH_WINNT | ARCH_OS2 );
3000       else if (strcsequal(p,"Samba")) {
3001         arch = ARCH_SAMBA;
3002         break;
3003       }
3004  
3005       p += strlen(p) + 2;
3006     }
3007     
3008   switch ( arch ) {
3009   case ARCH_SAMBA:
3010     strcpy(remote_arch,"Samba");
3011     break;
3012   case ARCH_WFWG:
3013     strcpy(remote_arch,"WfWg");
3014     break;
3015   case ARCH_WIN95:
3016     strcpy(remote_arch,"Win95");
3017     break;
3018   case ARCH_WINNT:
3019     strcpy(remote_arch,"WinNT");
3020     break;
3021   case ARCH_OS2:
3022     strcpy(remote_arch,"OS2");
3023     break;
3024   default:
3025     strcpy(remote_arch,"UNKNOWN");
3026     break;
3027   }
3028  
3029   /* possibly reload - change of architecture */
3030   reload_services(True);      
3031     
3032   /* a special case to stop password server loops */
3033   if (Index == 1 && strequal(remote_machine,myhostname) && 
3034       lp_security()==SEC_SERVER)
3035     exit_server("Password server loop!");
3036   
3037   /* Check for protocols, most desirable first */
3038   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
3039     {
3040       p = smb_buf(inbuf)+1;
3041       Index = 0;
3042       if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
3043         while (p < (smb_buf(inbuf) + bcc))
3044           { 
3045             if (strequal(p,supported_protocols[protocol].proto_name))
3046               choice = Index;
3047             Index++;
3048             p += strlen(p) + 2;
3049           }
3050       if(choice != -1)
3051         break;
3052     }
3053   
3054   SSVAL(outbuf,smb_vwv0,choice);
3055   if(choice != -1) {
3056     extern fstring remote_proto;
3057     strcpy(remote_proto,supported_protocols[protocol].short_name);
3058     reload_services(True);          
3059     outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
3060     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
3061   }
3062   else {
3063     DEBUG(0,("No protocol supported !\n"));
3064   }
3065   SSVAL(outbuf,smb_vwv0,choice);
3066   
3067   DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3068
3069   return(outsize);
3070 }
3071
3072
3073 /****************************************************************************
3074 close all open files for a connection
3075 ****************************************************************************/
3076 static void close_open_files(int cnum)
3077 {
3078   int i;
3079   for (i=0;i<MAX_OPEN_FILES;i++)
3080     if( Files[i].cnum == cnum && Files[i].open) {
3081       close_file(i);
3082     }
3083 }
3084
3085
3086
3087 /****************************************************************************
3088 close a cnum
3089 ****************************************************************************/
3090 void close_cnum(int cnum, uint16 vuid)
3091 {
3092   DirCacheFlush(SNUM(cnum));
3093
3094   unbecome_user();
3095
3096   if (!OPEN_CNUM(cnum))
3097     {
3098       DEBUG(0,("Can't close cnum %d\n",cnum));
3099       return;
3100     }
3101
3102   DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3103                           timestring(),
3104                           remote_machine,client_addr(),
3105                           lp_servicename(SNUM(cnum))));
3106
3107   yield_connection(cnum,
3108                    lp_servicename(SNUM(cnum)),
3109                    lp_max_connections(SNUM(cnum)));
3110
3111   if (lp_status(SNUM(cnum)))
3112     yield_connection(cnum,"STATUS.",MAXSTATUS);
3113
3114   close_open_files(cnum);
3115   dptr_closecnum(cnum);
3116
3117   /* execute any "postexec = " line */
3118   if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
3119     {
3120       pstring cmd;
3121       strcpy(cmd,lp_postexec(SNUM(cnum)));
3122       standard_sub(cnum,cmd);
3123       smbrun(cmd,NULL,False);
3124       unbecome_user();
3125     }
3126
3127   unbecome_user();
3128   /* execute any "root postexec = " line */
3129   if (*lp_rootpostexec(SNUM(cnum)))
3130     {
3131       pstring cmd;
3132       strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3133       standard_sub(cnum,cmd);
3134       smbrun(cmd,NULL,False);
3135     }
3136
3137   Connections[cnum].open = False;
3138   num_connections_open--;
3139   if (Connections[cnum].ngroups && Connections[cnum].groups)
3140     {
3141       if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3142         free(Connections[cnum].groups);
3143       free(Connections[cnum].igroups);
3144       Connections[cnum].groups = NULL;
3145       Connections[cnum].igroups = NULL;
3146       Connections[cnum].ngroups = 0;
3147     }
3148
3149   string_set(&Connections[cnum].user,"");
3150   string_set(&Connections[cnum].dirpath,"");
3151   string_set(&Connections[cnum].connectpath,"");
3152 }
3153
3154
3155 /****************************************************************************
3156 simple routines to do connection counting
3157 ****************************************************************************/
3158 BOOL yield_connection(int cnum,char *name,int max_connections)
3159 {
3160   struct connect_record crec;
3161   pstring fname;
3162   FILE *f;
3163   int mypid = getpid();
3164   int i;
3165
3166   DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3167
3168   if (max_connections <= 0)
3169     return(True);
3170
3171   bzero(&crec,sizeof(crec));
3172
3173   strcpy(fname,lp_lockdir());
3174   standard_sub(cnum,fname);
3175   trim_string(fname,"","/");
3176
3177   strcat(fname,"/");
3178   strcat(fname,name);
3179   strcat(fname,".LCK");
3180
3181   f = fopen(fname,"r+");
3182   if (!f)
3183     {
3184       DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
3185       return(False);
3186     }
3187
3188   fseek(f,0,SEEK_SET);
3189
3190   /* find a free spot */
3191   for (i=0;i<max_connections;i++)
3192     {
3193       if (fread(&crec,sizeof(crec),1,f) != 1)
3194         {
3195           DEBUG(2,("Entry not found in lock file %s\n",fname));
3196           fclose(f);
3197           return(False);
3198         }
3199       if (crec.pid == mypid && crec.cnum == cnum)
3200         break;
3201     }
3202
3203   if (crec.pid != mypid || crec.cnum != cnum)
3204     {
3205       fclose(f);
3206       DEBUG(2,("Entry not found in lock file %s\n",fname));
3207       return(False);
3208     }
3209
3210   bzero((void *)&crec,sizeof(crec));
3211   
3212   /* remove our mark */
3213   if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3214       fwrite(&crec,sizeof(crec),1,f) != 1)
3215     {
3216       DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3217       fclose(f);
3218       return(False);
3219     }
3220
3221   DEBUG(3,("Yield successful\n"));
3222
3223   fclose(f);
3224   return(True);
3225 }
3226
3227
3228 /****************************************************************************
3229 simple routines to do connection counting
3230 ****************************************************************************/
3231 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3232 {
3233   struct connect_record crec;
3234   pstring fname;
3235   FILE *f;
3236   int snum = SNUM(cnum);
3237   int i,foundi= -1;
3238   int total_recs;
3239
3240   if (max_connections <= 0)
3241     return(True);
3242
3243   DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3244
3245   strcpy(fname,lp_lockdir());
3246   standard_sub(cnum,fname);
3247   trim_string(fname,"","/");
3248
3249   if (!directory_exist(fname,NULL))
3250     mkdir(fname,0755);
3251
3252   strcat(fname,"/");
3253   strcat(fname,name);
3254   strcat(fname,".LCK");
3255
3256   if (!file_exist(fname,NULL))
3257     {
3258       int oldmask = umask(022);
3259       f = fopen(fname,"w");
3260       if (f) fclose(f);
3261       umask(oldmask);
3262     }
3263
3264   total_recs = file_size(fname) / sizeof(crec);
3265
3266   f = fopen(fname,"r+");
3267
3268   if (!f)
3269     {
3270       DEBUG(1,("couldn't open lock file %s\n",fname));
3271       return(False);
3272     }
3273
3274   /* find a free spot */
3275   for (i=0;i<max_connections;i++)
3276     {
3277
3278       if (i>=total_recs || 
3279           fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3280           fread(&crec,sizeof(crec),1,f) != 1)
3281         {
3282           if (foundi < 0) foundi = i;
3283           break;
3284         }
3285
3286       if (Clear && crec.pid && !process_exists(crec.pid))
3287         {
3288           fseek(f,i*sizeof(crec),SEEK_SET);
3289           bzero((void *)&crec,sizeof(crec));
3290           fwrite(&crec,sizeof(crec),1,f);
3291           if (foundi < 0) foundi = i;
3292           continue;
3293         }
3294       if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
3295         {
3296           foundi=i;
3297           if (!Clear) break;
3298         }
3299     }  
3300
3301   if (foundi < 0)
3302     {
3303       DEBUG(3,("no free locks in %s\n",fname));
3304       fclose(f);
3305       return(False);
3306     }      
3307
3308   /* fill in the crec */
3309   bzero((void *)&crec,sizeof(crec));
3310   crec.magic = 0x280267;
3311   crec.pid = getpid();
3312   crec.cnum = cnum;
3313   crec.uid = Connections[cnum].uid;
3314   crec.gid = Connections[cnum].gid;
3315   StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
3316   crec.start = time(NULL);
3317
3318   StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
3319   StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
3320   
3321   /* make our mark */
3322   if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
3323       fwrite(&crec,sizeof(crec),1,f) != 1)
3324     {
3325       fclose(f);
3326       return(False);
3327     }
3328
3329   fclose(f);
3330   return(True);
3331 }
3332
3333 #if DUMP_CORE
3334 /*******************************************************************
3335 prepare to dump a core file - carefully!
3336 ********************************************************************/
3337 static BOOL dump_core(void)
3338 {
3339   char *p;
3340   pstring dname;
3341   strcpy(dname,debugf);
3342   if ((p=strrchr(dname,'/'))) *p=0;
3343   strcat(dname,"/corefiles");
3344   mkdir(dname,0700);
3345   sys_chown(dname,getuid(),getgid());
3346   chmod(dname,0700);
3347   if (chdir(dname)) return(False);
3348   umask(~(0700));
3349
3350 #ifndef NO_GETRLIMIT
3351 #ifdef RLIMIT_CORE
3352   {
3353     struct rlimit rlp;
3354     getrlimit(RLIMIT_CORE, &rlp);
3355     rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
3356     setrlimit(RLIMIT_CORE, &rlp);
3357     getrlimit(RLIMIT_CORE, &rlp);
3358     DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
3359   }
3360 #endif
3361 #endif
3362
3363
3364   DEBUG(0,("Dumping core in %s\n",dname));
3365   return(True);
3366 }
3367 #endif
3368
3369 /****************************************************************************
3370 exit the server
3371 ****************************************************************************/
3372 void exit_server(char *reason)
3373 {
3374   static int firsttime=1;
3375   int i;
3376
3377   if (!firsttime) exit(0);
3378   firsttime = 0;
3379
3380   unbecome_user();
3381   DEBUG(2,("Closing connections\n"));
3382   for (i=0;i<MAX_CONNECTIONS;i++)
3383     if (Connections[i].open)
3384       close_cnum(i,-1);
3385 #ifdef DFS_AUTH
3386   if (dcelogin_atmost_once)
3387     dfs_unlogin();
3388 #endif
3389   if (!reason) {   
3390     int oldlevel = DEBUGLEVEL;
3391     DEBUGLEVEL = 10;
3392     DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
3393     if (last_inbuf)
3394       show_msg(last_inbuf);
3395     DEBUGLEVEL = oldlevel;
3396     DEBUG(0,("===============================================================\n"));
3397 #if DUMP_CORE
3398     if (dump_core()) return;
3399 #endif
3400   }    
3401
3402 #ifdef FAST_SHARE_MODES
3403   stop_share_mode_mgmt();
3404 #endif /* FAST_SHARE_MODES */
3405
3406   DEBUG(3,("%s Server exit  (%s)\n",timestring(),reason?reason:""));
3407   exit(0);
3408 }
3409
3410 /****************************************************************************
3411 do some standard substitutions in a string
3412 ****************************************************************************/
3413 void standard_sub(int cnum,char *s)
3414 {
3415   if (!strchr(s,'%')) return;
3416
3417   if (VALID_CNUM(cnum))
3418     {
3419       string_sub(s,"%S",lp_servicename(Connections[cnum].service));
3420       string_sub(s,"%P",Connections[cnum].connectpath);
3421       string_sub(s,"%u",Connections[cnum].user);
3422       if (strstr(s,"%H")) {
3423         char *home = get_home_dir(Connections[cnum].user);
3424         if (home) string_sub(s,"%H",home);
3425       }
3426       string_sub(s,"%g",gidtoname(Connections[cnum].gid));
3427     }
3428   standard_sub_basic(s);
3429 }
3430
3431 /*
3432 These flags determine some of the permissions required to do an operation 
3433
3434 Note that I don't set NEED_WRITE on some write operations because they
3435 are used by some brain-dead clients when printing, and I don't want to
3436 force write permissions on print services.
3437 */
3438 #define AS_USER (1<<0)
3439 #define NEED_WRITE (1<<1)
3440 #define TIME_INIT (1<<2)
3441 #define CAN_IPC (1<<3)
3442 #define AS_GUEST (1<<5)
3443
3444
3445 /* 
3446    define a list of possible SMB messages and their corresponding
3447    functions. Any message that has a NULL function is unimplemented -
3448    please feel free to contribute implementations!
3449 */
3450 struct smb_message_struct
3451 {
3452   int code;
3453   char *name;
3454   int (*fn)();
3455   int flags;
3456 #if PROFILING
3457   unsigned long time;
3458 #endif
3459 }
3460  smb_messages[] = {
3461
3462     /* CORE PROTOCOL */
3463
3464    {SMBnegprot,"SMBnegprot",reply_negprot,0},
3465    {SMBtcon,"SMBtcon",reply_tcon,0},
3466    {SMBtdis,"SMBtdis",reply_tdis,0},
3467    {SMBexit,"SMBexit",reply_exit,0},
3468    {SMBioctl,"SMBioctl",reply_ioctl,0},
3469    {SMBecho,"SMBecho",reply_echo,0},
3470    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
3471    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
3472    {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
3473    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
3474    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
3475    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
3476    {SMBsearch,"SMBsearch",reply_search,AS_USER},
3477    {SMBopen,"SMBopen",reply_open,AS_USER},
3478
3479    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
3480    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
3481    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
3482
3483    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
3484    {SMBread,"SMBread",reply_read,AS_USER},
3485    {SMBwrite,"SMBwrite",reply_write,AS_USER},
3486    {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
3487    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
3488    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
3489    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
3490    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
3491
3492    /* this is a Pathworks specific call, allowing the 
3493       changing of the root path */
3494    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
3495
3496    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
3497    {SMBflush,"SMBflush",reply_flush,AS_USER},
3498    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
3499    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
3500    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
3501    {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
3502    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
3503    {SMBlock,"SMBlock",reply_lock,AS_USER},
3504    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
3505    
3506    /* CORE+ PROTOCOL FOLLOWS */
3507    
3508    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
3509    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
3510    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
3511    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
3512    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
3513    
3514    /* LANMAN1.0 PROTOCOL FOLLOWS */
3515    
3516    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
3517    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
3518    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
3519    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
3520    {SMBwritec,"SMBwritec",NULL,AS_USER},
3521    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
3522    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
3523    {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
3524    {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
3525    {SMBioctls,"SMBioctls",NULL,AS_USER},
3526    {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
3527    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
3528    
3529    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
3530    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
3531    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
3532    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
3533    
3534    {SMBffirst,"SMBffirst",reply_search,AS_USER},
3535    {SMBfunique,"SMBfunique",reply_search,AS_USER},
3536    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
3537
3538    /* LANMAN2.0 PROTOCOL FOLLOWS */
3539    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
3540    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
3541    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
3542    {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
3543
3544    /* messaging routines */
3545    {SMBsends,"SMBsends",reply_sends,AS_GUEST},
3546    {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
3547    {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
3548    {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
3549
3550    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
3551    
3552    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
3553    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
3554    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
3555    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
3556  };
3557
3558 /****************************************************************************
3559 return a string containing the function name of a SMB command
3560 ****************************************************************************/
3561 char *smb_fn_name(int type)
3562 {
3563   static char *unknown_name = "SMBunknown";
3564   static int num_smb_messages = 
3565     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3566   int match;
3567
3568   for (match=0;match<num_smb_messages;match++)
3569     if (smb_messages[match].code == type)
3570       break;
3571
3572   if (match == num_smb_messages)
3573     return(unknown_name);
3574
3575   return(smb_messages[match].name);
3576 }
3577
3578
3579 /****************************************************************************
3580 do a switch on the message type, and return the response size
3581 ****************************************************************************/
3582 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
3583 {
3584   static int pid= -1;
3585   int outsize = 0;
3586   static int num_smb_messages = 
3587     sizeof(smb_messages) / sizeof(struct smb_message_struct);
3588   int match;
3589
3590 #if PROFILING
3591   struct timeval msg_start_time;
3592   struct timeval msg_end_time;
3593   static unsigned long total_time = 0;
3594
3595   GetTimeOfDay(&msg_start_time);
3596 #endif
3597
3598   if (pid == -1)
3599     pid = getpid();
3600
3601   errno = 0;
3602   last_message = type;
3603
3604   /* make sure this is an SMB packet */
3605   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
3606     {
3607       DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
3608       return(-1);
3609     }
3610
3611   for (match=0;match<num_smb_messages;match++)
3612     if (smb_messages[match].code == type)
3613       break;
3614
3615   if (match == num_smb_messages)
3616     {
3617       DEBUG(0,("Unknown message type %d!\n",type));
3618       outsize = reply_unknown(inbuf,outbuf);
3619     }
3620   else
3621     {
3622       DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
3623       if (smb_messages[match].fn)
3624         {
3625           int cnum = SVAL(inbuf,smb_tid);
3626           int flags = smb_messages[match].flags;
3627           uint16 session_tag = SVAL(inbuf,smb_uid);
3628
3629           /* does this protocol need to be run as root? */
3630           if (!(flags & AS_USER))
3631             unbecome_user();
3632
3633           /* does this protocol need to be run as the connected user? */
3634           if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
3635             if (flags & AS_GUEST) 
3636               flags &= ~AS_USER;
3637             else
3638               return(ERROR(ERRSRV,ERRinvnid));
3639           }
3640           /* this code is to work around a bug is MS client 3 without
3641              introducing a security hole - it needs to be able to do
3642              print queue checks as guest if it isn't logged in properly */
3643           if (flags & AS_USER)
3644             flags &= ~AS_GUEST;
3645
3646           /* does it need write permission? */
3647           if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
3648             return(ERROR(ERRSRV,ERRaccess));
3649
3650           /* ipc services are limited */
3651           if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
3652             return(ERROR(ERRSRV,ERRaccess));        
3653
3654           /* load service specific parameters */
3655           if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
3656             return(ERROR(ERRSRV,ERRaccess));
3657
3658           /* does this protocol need to be run as guest? */
3659           if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
3660             return(ERROR(ERRSRV,ERRaccess));
3661
3662           last_inbuf = inbuf;
3663
3664           outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
3665         }
3666       else
3667         {
3668           outsize = reply_unknown(inbuf,outbuf);
3669         }
3670     }
3671
3672 #if PROFILING
3673   GetTimeOfDay(&msg_end_time);
3674   if (!(smb_messages[match].flags & TIME_INIT))
3675     {
3676       smb_messages[match].time = 0;
3677       smb_messages[match].flags |= TIME_INIT;
3678     }
3679   {
3680     unsigned long this_time =     
3681       (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
3682         (msg_end_time.tv_usec - msg_start_time.tv_usec);
3683     smb_messages[match].time += this_time;
3684     total_time += this_time;
3685   }
3686   DEBUG(2,("TIME %s  %d usecs   %g pct\n",
3687            smb_fn_name(type),smb_messages[match].time,
3688         (100.0*smb_messages[match].time) / total_time));
3689 #endif
3690
3691   return(outsize);
3692 }
3693
3694
3695 /****************************************************************************
3696   construct a chained reply and add it to the already made reply
3697   **************************************************************************/
3698 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
3699 {
3700   static char *orig_inbuf;
3701   static char *orig_outbuf;
3702   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
3703   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
3704   char *inbuf2, *outbuf2;
3705   int outsize2;
3706   char inbuf_saved[smb_wct];
3707   char outbuf_saved[smb_wct];
3708   extern int chain_size;
3709   int wct = CVAL(outbuf,smb_wct);
3710   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
3711
3712   /* maybe its not chained */
3713   if (smb_com2 == 0xFF) {
3714     CVAL(outbuf,smb_vwv0) = 0xFF;
3715     return outsize;
3716   }
3717
3718   if (chain_size == 0) {
3719     /* this is the first part of the chain */
3720     orig_inbuf = inbuf;
3721     orig_outbuf = outbuf;
3722   }
3723
3724   /* we need to tell the client where the next part of the reply will be */
3725   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
3726   CVAL(outbuf,smb_vwv0) = smb_com2;
3727
3728   /* remember how much the caller added to the chain, only counting stuff
3729      after the parameter words */
3730   chain_size += outsize - smb_wct;
3731
3732   /* work out pointers into the original packets. The
3733      headers on these need to be filled in */
3734   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
3735   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
3736
3737   /* remember the original command type */
3738   smb_com1 = CVAL(orig_inbuf,smb_com);
3739
3740   /* save the data which will be overwritten by the new headers */
3741   memcpy(inbuf_saved,inbuf2,smb_wct);
3742   memcpy(outbuf_saved,outbuf2,smb_wct);
3743
3744   /* give the new packet the same header as the last part of the SMB */
3745   memmove(inbuf2,inbuf,smb_wct);
3746
3747   /* create the in buffer */
3748   CVAL(inbuf2,smb_com) = smb_com2;
3749
3750   /* create the out buffer */