290181fb9ee04f7b198b905fea72fa050d524d72
[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 /* Oplock ipc UDP socket. */
88 int oplock_sock = -1;
89 uint16 oplock_port = 0;
90 /* Current number of oplocks we have outstanding. */
91 int32 global_oplocks_open = 0;
92
93 BOOL global_oplock_break = False;
94
95 extern fstring remote_machine;
96
97 pstring OriginalDir;
98
99 /* these can be set by some functions to override the error codes */
100 int unix_ERR_class=SUCCESS;
101 int unix_ERR_code=0;
102
103
104 extern int extra_time_offset;
105
106 extern pstring myhostname;
107
108 static int find_free_connection(int hash);
109
110 /* for readability... */
111 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
112 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
113 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
114 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
115 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
116
117 /****************************************************************************
118   when exiting, take the whole family
119 ****************************************************************************/
120 void  *dflt_sig(void)
121 {
122   exit_server("caught signal");
123   return 0; /* Keep -Wall happy :-) */
124 }
125 /****************************************************************************
126   Send a SIGTERM to our process group.
127 *****************************************************************************/
128 void  killkids(void)
129 {
130   if(am_parent) kill(0,SIGTERM);
131 }
132
133 /****************************************************************************
134   change a dos mode to a unix mode
135     base permission for files:
136          everybody gets read bit set
137          dos readonly is represented in unix by removing everyone's write bit
138          dos archive is represented in unix by the user's execute bit
139          dos system is represented in unix by the group's execute bit
140          dos hidden is represented in unix by the other's execute bit
141          Then apply create mask,
142          then add force bits.
143     base permission for directories:
144          dos directory is represented in unix by unix's dir bit and the exec bit
145          Then apply create mask,
146          then add force bits.
147 ****************************************************************************/
148 mode_t unix_mode(int cnum,int dosmode)
149 {
150   mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
151
152   if ( !IS_DOS_READONLY(dosmode) )
153     result |= (S_IWUSR | S_IWGRP | S_IWOTH);
154  
155   if (IS_DOS_DIR(dosmode)) {
156     /* We never make directories read only for the owner as under DOS a user
157        can always create a file in a read-only directory. */
158     result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
159     /* Apply directory mask */
160     result &= lp_dir_mode(SNUM(cnum));
161     /* Add in force bits */
162     result |= lp_force_dir_mode(SNUM(cnum));
163   } else { 
164     if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
165       result |= S_IXUSR;
166
167     if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
168       result |= S_IXGRP;
169  
170     if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
171       result |= S_IXOTH;  
172  
173     /* Apply mode mask */
174     result &= lp_create_mode(SNUM(cnum));
175     /* Add in force bits */
176     result |= lp_force_create_mode(SNUM(cnum));
177   }
178   return(result);
179 }
180
181
182 /****************************************************************************
183   change a unix mode to a dos mode
184 ****************************************************************************/
185 int dos_mode(int cnum,char *path,struct stat *sbuf)
186 {
187   int result = 0;
188   extern struct current_user current_user;
189
190   DEBUG(8,("dos_mode: %d %s\n", cnum, path));
191
192   if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
193     if (!((sbuf->st_mode & S_IWOTH) ||
194           Connections[cnum].admin_user ||
195           ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
196           ((sbuf->st_mode & S_IWGRP) && 
197            in_group(sbuf->st_gid,current_user.gid,
198                     current_user.ngroups,current_user.igroups))))
199       result |= aRONLY;
200   } else {
201     if ((sbuf->st_mode & S_IWUSR) == 0)
202       result |= aRONLY;
203   }
204
205   if (MAP_ARCHIVE(cnum) && ((sbuf->st_mode & S_IXUSR) != 0))
206     result |= aARCH;
207
208   if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
209     result |= aSYSTEM;
210
211   if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
212     result |= aHIDDEN;   
213   
214   if (S_ISDIR(sbuf->st_mode))
215     result = aDIR | (result & aRONLY);
216
217 #if LINKS_READ_ONLY
218   if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
219     result |= aRONLY;
220 #endif
221
222   /* hide files with a name starting with a . */
223   if (lp_hide_dot_files(SNUM(cnum)))
224     {
225       char *p = strrchr(path,'/');
226       if (p)
227         p++;
228       else
229         p = path;
230       
231       if (p[0] == '.' && p[1] != '.' && p[1] != 0)
232         result |= aHIDDEN;
233     }
234
235   /* Optimization : Only call is_hidden_path if it's not already
236      hidden. */
237   if (!(result & aHIDDEN) && IS_HIDDEN_PATH(cnum,path))
238   {
239     result |= aHIDDEN;
240   }
241
242   DEBUG(8,("dos_mode returning "));
243
244   if (result & aHIDDEN) DEBUG(8, ("h"));
245   if (result & aRONLY ) DEBUG(8, ("r"));
246   if (result & aSYSTEM) DEBUG(8, ("s"));
247   if (result & aDIR   ) DEBUG(8, ("d"));
248   if (result & aARCH  ) DEBUG(8, ("a"));
249
250   DEBUG(8,("\n"));
251
252   return(result);
253 }
254
255
256 /*******************************************************************
257 chmod a file - but preserve some bits
258 ********************************************************************/
259 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
260 {
261   struct stat st1;
262   int mask=0;
263   int tmp;
264   int unixmode;
265
266   if (!st) {
267     st = &st1;
268     if (sys_stat(fname,st)) return(-1);
269   }
270
271   if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
272
273   if (dos_mode(cnum,fname,st) == dosmode) return(0);
274
275   unixmode = unix_mode(cnum,dosmode);
276
277   /* preserve the s bits */
278   mask |= (S_ISUID | S_ISGID);
279
280   /* preserve the t bit */
281 #ifdef S_ISVTX
282   mask |= S_ISVTX;
283 #endif
284
285   /* possibly preserve the x bits */
286   if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
287   if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
288   if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
289
290   unixmode |= (st->st_mode & mask);
291
292   /* if we previously had any r bits set then leave them alone */
293   if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
294     unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
295     unixmode |= tmp;
296   }
297
298   /* if we previously had any w bits set then leave them alone 
299    if the new mode is not rdonly */
300   if (!IS_DOS_READONLY(dosmode) &&
301       (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
302     unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
303     unixmode |= tmp;
304   }
305
306   return(sys_chmod(fname,unixmode));
307 }
308
309
310 /****************************************************************************
311 check if two filenames are equal
312
313 this needs to be careful about whether we are case sensitive
314 ****************************************************************************/
315 static BOOL fname_equal(char *name1, char *name2)
316 {
317   int l1 = strlen(name1);
318   int l2 = strlen(name2);
319
320   /* handle filenames ending in a single dot */
321   if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
322     {
323       BOOL ret;
324       name1[l1-1] = 0;
325       ret = fname_equal(name1,name2);
326       name1[l1-1] = '.';
327       return(ret);
328     }
329
330   if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
331     {
332       BOOL ret;
333       name2[l2-1] = 0;
334       ret = fname_equal(name1,name2);
335       name2[l2-1] = '.';
336       return(ret);
337     }
338
339   /* now normal filename handling */
340   if (case_sensitive)
341     return(strcmp(name1,name2) == 0);
342
343   return(strequal(name1,name2));
344 }
345
346
347 /****************************************************************************
348 mangle the 2nd name and check if it is then equal to the first name
349 ****************************************************************************/
350 static BOOL mangled_equal(char *name1, char *name2)
351 {
352   pstring tmpname;
353
354   if (is_8_3(name2, True))
355     return(False);
356
357   strcpy(tmpname,name2);
358   mangle_name_83(tmpname);
359
360   return(strequal(name1,tmpname));
361 }
362
363
364 /****************************************************************************
365 scan a directory to find a filename, matching without case sensitivity
366
367 If the name looks like a mangled name then try via the mangling functions
368 ****************************************************************************/
369 static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache)
370 {
371   void *cur_dir;
372   char *dname;
373   BOOL mangled;
374   pstring name2;
375
376   mangled = is_mangled(name);
377
378   /* handle null paths */
379   if (*path == 0)
380     path = ".";
381
382   if (docache && (dname = DirCacheCheck(path,name,SNUM(cnum)))) {
383     strcpy(name, dname);        
384     return(True);
385   }      
386
387   if (mangled)
388     check_mangled_stack(name);
389
390   /* open the directory */
391   if (!(cur_dir = OpenDir(cnum, path, True))) 
392     {
393       DEBUG(3,("scan dir didn't open dir [%s]\n",path));
394       return(False);
395     }
396
397   /* now scan for matching names */
398   while ((dname = ReadDirName(cur_dir))) 
399     {
400       if (*dname == '.' &&
401           (strequal(dname,".") || strequal(dname,"..")))
402         continue;
403
404       pstrcpy(name2,dname);
405       if (!name_map_mangle(name2,False,SNUM(cnum))) continue;
406
407       if ((mangled && mangled_equal(name,name2))
408           || fname_equal(name, name2)) /* name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra) */
409         {
410           /* we've found the file, change it's name and return */
411           if (docache) DirCacheAdd(path,name,dname,SNUM(cnum));
412           strcpy(name, dname);
413           CloseDir(cur_dir);
414           return(True);
415         }
416     }
417
418   CloseDir(cur_dir);
419   return(False);
420 }
421
422 /****************************************************************************
423 This routine is called to convert names from the dos namespace to unix
424 namespace. It needs to handle any case conversions, mangling, format
425 changes etc.
426
427 We assume that we have already done a chdir() to the right "root" directory
428 for this service.
429
430 The function will return False if some part of the name except for the last
431 part cannot be resolved
432
433 If the saved_last_component != 0, then the unmodified last component
434 of the pathname is returned there. This is used in an exceptional
435 case in reply_mv (so far). If saved_last_component == 0 then nothing
436 is returned there.
437
438 The bad_path arg is set to True if the filename walk failed. This is
439 used to pick the correct error code to return between ENOENT and ENOTDIR
440 as Windows applications depend on ERRbadpath being returned if a component
441 of a pathname does not exist.
442 ****************************************************************************/
443 BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path)
444 {
445   struct stat st;
446   char *start, *end;
447   pstring dirpath;
448   int saved_errno;
449
450   *dirpath = 0;
451   *bad_path = False;
452
453   if(saved_last_component)
454     *saved_last_component = 0;
455
456   /* convert to basic unix format - removing \ chars and cleaning it up */
457   unix_format(name);
458   unix_clean_name(name);
459
460   /* names must be relative to the root of the service - trim any leading /.
461    also trim trailing /'s */
462   trim_string(name,"/","/");
463
464   /*
465    * Ensure saved_last_component is valid even if file exists.
466    */
467   if(saved_last_component) {
468     end = strrchr(name, '/');
469     if(end)
470       strcpy(saved_last_component, end + 1);
471     else
472       strcpy(saved_last_component, name);
473   }
474
475   if (!case_sensitive && 
476       (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
477     strnorm(name);
478
479   /* check if it's a printer file */
480   if (Connections[cnum].printer)
481     {
482       if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
483         {
484           char *s;
485           fstring name2;
486           sprintf(name2,"%.6s.XXXXXX",remote_machine);
487           /* sanitise the name */
488           for (s=name2 ; *s ; s++)
489             if (!issafe(*s)) *s = '_';
490           strcpy(name,(char *)mktemp(name2));     
491         }      
492       return(True);
493     }
494
495   /* stat the name - if it exists then we are all done! */
496   if (sys_stat(name,&st) == 0)
497     return(True);
498
499   saved_errno = errno;
500
501   DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
502
503   /* a special case - if we don't have any mangling chars and are case
504      sensitive then searching won't help */
505   if (case_sensitive && !is_mangled(name) && 
506       !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
507     return(False);
508
509   /* now we need to recursively match the name against the real 
510      directory structure */
511
512   start = name;
513   while (strncmp(start,"./",2) == 0)
514     start += 2;
515
516   /* now match each part of the path name separately, trying the names
517      as is first, then trying to scan the directory for matching names */
518   for (;start;start = (end?end+1:(char *)NULL)) 
519     {
520       /* pinpoint the end of this section of the filename */
521       end = strchr(start, '/');
522
523       /* chop the name at this point */
524       if (end)  *end = 0;
525
526       if(saved_last_component != 0)
527         strcpy(saved_last_component, end ? end + 1 : start);
528
529       /* check if the name exists up to this point */
530       if (sys_stat(name, &st) == 0) 
531         {
532           /* it exists. it must either be a directory or this must be
533              the last part of the path for it to be OK */
534           if (end && !(st.st_mode & S_IFDIR)) 
535             {
536               /* an intermediate part of the name isn't a directory */
537               DEBUG(5,("Not a dir %s\n",start));
538               *end = '/';
539               return(False);
540             }
541         }
542       else 
543         {
544           pstring rest;
545
546           *rest = 0;
547
548           /* remember the rest of the pathname so it can be restored
549              later */
550           if (end) pstrcpy(rest,end+1);
551
552           /* try to find this part of the path in the directory */
553           if (strchr(start,'?') || strchr(start,'*') ||
554               !scan_directory(dirpath, start, cnum, end?True:False))
555             {
556               if (end) 
557                 {
558                   /* an intermediate part of the name can't be found */
559                   DEBUG(5,("Intermediate not found %s\n",start));
560                   *end = '/';
561                   /* We need to return the fact that the intermediate
562                      name resolution failed. This is used to return an
563                      error of ERRbadpath rather than ERRbadfile. Some
564                      Windows applications depend on the difference between
565                      these two errors.
566                    */
567                   *bad_path = True;
568                   return(False);
569                 }
570               
571               /* just the last part of the name doesn't exist */
572               /* we may need to strupper() or strlower() it in case
573                  this conversion is being used for file creation 
574                  purposes */
575               /* if the filename is of mixed case then don't normalise it */
576               if (!case_preserve && 
577                   (!strhasupper(start) || !strhaslower(start)))         
578                 strnorm(start);
579
580               /* check on the mangled stack to see if we can recover the 
581                  base of the filename */
582               if (is_mangled(start))
583                 check_mangled_stack(start);
584
585               DEBUG(5,("New file %s\n",start));
586               return(True); 
587             }
588
589           /* restore the rest of the string */
590           if (end) 
591             {
592               strcpy(start+strlen(start)+1,rest);
593               end = start + strlen(start);
594             }
595         }
596
597       /* add to the dirpath that we have resolved so far */
598       if (*dirpath) strcat(dirpath,"/");
599       strcat(dirpath,start);
600
601       /* restore the / that we wiped out earlier */
602       if (end) *end = '/';
603     }
604   
605   /* the name has been resolved */
606   DEBUG(5,("conversion finished %s\n",name));
607   return(True);
608 }
609
610
611 /****************************************************************************
612 normalise for DOS usage 
613 ****************************************************************************/
614 static void disk_norm(int *bsize,int *dfree,int *dsize)
615 {
616   /* check if the disk is beyond the max disk size */
617   int maxdisksize = lp_maxdisksize();
618   if (maxdisksize) {
619     /* convert to blocks - and don't overflow */
620     maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
621     if (*dsize > maxdisksize) *dsize = maxdisksize;
622     if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop 
623                                                          applications getting 
624                                                          div by 0 errors */
625   }  
626
627   while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) 
628     {
629       *dfree /= 2;
630       *dsize /= 2;
631       *bsize *= 2;
632       if (*bsize > WORDMAX )
633         {
634           *bsize = WORDMAX;
635           if (*dsize > WORDMAX)
636             *dsize = WORDMAX;
637           if (*dfree >  WORDMAX)
638             *dfree = WORDMAX;
639           break;
640         }
641     }
642 }
643
644 /****************************************************************************
645   return number of 1K blocks available on a path and total number 
646 ****************************************************************************/
647 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
648 {
649   char *df_command = lp_dfree_command();
650   int dfree_retval;
651 #ifdef QUOTAS
652   int dfreeq_retval;
653   int dfreeq = 0;
654   int bsizeq = *bsize;
655   int dsizeq = *dsize;
656 #endif
657
658 #ifndef NO_STATFS
659 #ifdef USE_STATVFS
660   struct statvfs fs;
661 #else
662 #ifdef ULTRIX
663   struct fs_data fs;
664 #else
665   struct statfs fs;
666 #endif
667 #endif
668 #endif
669
670   /* possibly use system() to get the result */
671   if (df_command && *df_command)
672     {
673       int ret;
674       pstring syscmd;
675       pstring outfile;
676           
677       sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
678       sprintf(syscmd,"%s %s",df_command,path);
679       standard_sub_basic(syscmd);
680
681       ret = smbrun(syscmd,outfile,False);
682       DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
683           
684       {
685         FILE *f = fopen(outfile,"r");   
686         *dsize = 0;
687         *dfree = 0;
688         *bsize = 1024;
689         if (f)
690           {
691             fscanf(f,"%d %d %d",dsize,dfree,bsize);
692             fclose(f);
693           }
694         else
695           DEBUG(0,("Can't open %s\n",outfile));
696       }
697           
698       unlink(outfile);
699       disk_norm(bsize,dfree,dsize);
700       dfree_retval = ((*bsize)/1024)*(*dfree);
701 #ifdef QUOTAS
702       /* Ensure we return the min value between the users quota and
703          what's free on the disk. Thanks to Albrecht Gebhardt 
704          <albrecht.gebhardt@uni-klu.ac.at> for this fix.
705       */
706       if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
707         {
708           disk_norm(&bsizeq, &dfreeq, &dsizeq);
709           dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
710           dfree_retval =  ( dfree_retval < dfreeq_retval ) ? 
711                            dfree_retval : dfreeq_retval ;
712           /* maybe dfree and dfreeq are calculated using different bsizes 
713              so convert dfree from bsize into bsizeq */
714           *dfree = ((*dfree) * (*bsize)) / (bsizeq);
715           *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; 
716           *bsize = bsizeq;
717           *dsize = dsizeq;
718         }
719 #endif
720       return(dfree_retval);
721     }
722
723 #ifdef NO_STATFS
724   DEBUG(1,("Warning - no statfs function\n"));
725   return(1);
726 #else
727 #ifdef STATFS4
728   if (statfs(path,&fs,sizeof(fs),0) != 0)
729 #else
730 #ifdef USE_STATVFS
731     if (statvfs(path, &fs))
732 #else
733 #ifdef STATFS3
734       if (statfs(path,&fs,sizeof(fs)) == -1)     
735 #else
736         if (statfs(path,&fs) == -1)
737 #endif /* STATFS3 */
738 #endif /* USE_STATVFS */
739 #endif /* STATFS4 */
740           {
741             DEBUG(3,("dfree call failed code errno=%d\n",errno));
742             *bsize = 1024;
743             *dfree = 1;
744             *dsize = 1;
745             return(((*bsize)/1024)*(*dfree));
746           }
747
748 #ifdef ULTRIX
749   *bsize = 1024;
750   *dfree = fs.fd_req.bfree;
751   *dsize = fs.fd_req.btot;
752 #else
753 #ifdef USE_STATVFS
754   *bsize = fs.f_frsize;
755 #else
756 #ifdef USE_F_FSIZE
757   /* eg: osf1 has f_fsize = fundamental filesystem block size, 
758      f_bsize = optimal transfer block size (MX: 94-04-19) */
759   *bsize = fs.f_fsize;
760 #else
761   *bsize = fs.f_bsize;
762 #endif /* STATFS3 */
763 #endif /* USE_STATVFS */
764
765 #ifdef STATFS4
766   *dfree = fs.f_bfree;
767 #else
768   *dfree = fs.f_bavail;
769 #endif /* STATFS4 */
770   *dsize = fs.f_blocks;
771 #endif /* ULTRIX */
772
773 #if defined(SCO) || defined(ISC) || defined(MIPS)
774   *bsize = 512;
775 #endif
776
777 /* handle rediculous bsize values - some OSes are broken */
778 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
779
780   disk_norm(bsize,dfree,dsize);
781
782   if (*bsize < 256)
783     *bsize = 512;
784   if ((*dsize)<1)
785     {
786       DEBUG(0,("dfree seems to be broken on your system\n"));
787       *dsize = 20*1024*1024/(*bsize);
788       *dfree = MAX(1,*dfree);
789     }
790   dfree_retval = ((*bsize)/1024)*(*dfree);
791 #ifdef QUOTAS
792   /* Ensure we return the min value between the users quota and
793      what's free on the disk. Thanks to Albrecht Gebhardt 
794      <albrecht.gebhardt@uni-klu.ac.at> for this fix.
795   */
796   if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
797     {
798       disk_norm(&bsizeq, &dfreeq, &dsizeq);
799       dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
800       dfree_retval = ( dfree_retval < dfreeq_retval ) ? 
801                        dfree_retval : dfreeq_retval ;
802       /* maybe dfree and dfreeq are calculated using different bsizes 
803          so convert dfree from bsize into bsizeq */
804       *dfree = ((*dfree) * (*bsize)) / (bsizeq);
805       *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
806       *bsize = bsizeq;
807       *dsize = dsizeq;
808     }
809 #endif
810   return(dfree_retval);
811 #endif
812 }
813
814
815 /****************************************************************************
816 wrap it to get filenames right
817 ****************************************************************************/
818 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
819 {
820   return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
821 }
822
823
824
825 /****************************************************************************
826 check a filename - possibly caling reducename
827
828 This is called by every routine before it allows an operation on a filename.
829 It does any final confirmation necessary to ensure that the filename is
830 a valid one for the user to access.
831 ****************************************************************************/
832 BOOL check_name(char *name,int cnum)
833 {
834   BOOL ret;
835
836   errno = 0;
837
838   if( IS_VETO_PATH(cnum, name)) 
839     {
840       DEBUG(5,("file path name %s vetoed\n",name));
841       return(0);
842     }
843
844   ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
845
846   /* Check if we are allowing users to follow symlinks */
847   /* Patch from David Clerc <David.Clerc@cui.unige.ch>
848      University of Geneva */
849
850   if (!lp_symlinks(SNUM(cnum)))
851     {
852       struct stat statbuf;
853       if ( (sys_lstat(name,&statbuf) != -1) &&
854           (S_ISLNK(statbuf.st_mode)) )
855         {
856           DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
857           ret=0; 
858         }
859     }
860
861   if (!ret)
862     DEBUG(5,("check_name on %s failed\n",name));
863
864   return(ret);
865 }
866
867 /****************************************************************************
868 check a filename - possibly caling reducename
869 ****************************************************************************/
870 static void check_for_pipe(char *fname)
871 {
872   /* special case of pipe opens */
873   char s[10];
874   StrnCpy(s,fname,9);
875   strlower(s);
876   if (strstr(s,"pipe/"))
877     {
878       DEBUG(3,("Rejecting named pipe open for %s\n",fname));
879       unix_ERR_class = ERRSRV;
880       unix_ERR_code = ERRaccess;
881     }
882 }
883
884 /****************************************************************************
885 fd support routines - attempt to do a sys_open
886 ****************************************************************************/
887 static int fd_attempt_open(char *fname, int flags, int mode)
888 {
889   int fd = sys_open(fname,flags,mode);
890
891   /* Fix for files ending in '.' */
892   if((fd == -1) && (errno == ENOENT) &&
893      (strchr(fname,'.')==NULL))
894     {
895       strcat(fname,".");
896       fd = sys_open(fname,flags,mode);
897     }
898
899 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
900   if ((fd == -1) && (errno == ENAMETOOLONG))
901     {
902       int max_len;
903       char *p = strrchr(fname, '/');
904
905       if (p == fname)   /* name is "/xxx" */
906         {
907           max_len = pathconf("/", _PC_NAME_MAX);
908           p++;
909         }
910       else if ((p == NULL) || (p == fname))
911         {
912           p = fname;
913           max_len = pathconf(".", _PC_NAME_MAX);
914         }
915       else
916         {
917           *p = '\0';
918           max_len = pathconf(fname, _PC_NAME_MAX);
919           *p = '/';
920           p++;
921         }
922       if (strlen(p) > max_len)
923         {
924           char tmp = p[max_len];
925
926           p[max_len] = '\0';
927           if ((fd = sys_open(fname,flags,mode)) == -1)
928             p[max_len] = tmp;
929         }
930     }
931 #endif
932   return fd;
933 }
934
935 /****************************************************************************
936 fd support routines - attempt to find an already open file by dev
937 and inode - increments the ref_count of the returned file_fd_struct *.
938 ****************************************************************************/
939 static file_fd_struct *fd_get_already_open(struct stat *sbuf)
940 {
941   int i;
942   file_fd_struct *fd_ptr;
943
944   if(sbuf == 0)
945     return 0;
946
947   for(i = 0; i <= max_file_fd_used; i++) {
948     fd_ptr = &FileFd[i];
949     if((fd_ptr->ref_count > 0) &&
950        (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
951        (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
952       fd_ptr->ref_count++;
953       DEBUG(3,
954        ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
955         i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
956       return fd_ptr;
957     }
958   }
959   return 0;
960 }
961
962 /****************************************************************************
963 fd support routines - attempt to find a empty slot in the FileFd array.
964 Increments the ref_count of the returned entry.
965 ****************************************************************************/
966 static file_fd_struct *fd_get_new()
967 {
968   int i;
969   file_fd_struct *fd_ptr;
970
971   for(i = 0; i < MAX_OPEN_FILES; i++) {
972     fd_ptr = &FileFd[i];
973     if(fd_ptr->ref_count == 0) {
974       fd_ptr->dev = (uint32)-1;
975       fd_ptr->inode = (uint32)-1;
976       fd_ptr->fd = -1;
977       fd_ptr->fd_readonly = -1;
978       fd_ptr->fd_writeonly = -1;
979       fd_ptr->real_open_flags = -1;
980       fd_ptr->ref_count++;
981       /* Increment max used counter if neccessary, cuts down
982          on search time when re-using */
983       if(i > max_file_fd_used)
984         max_file_fd_used = i;
985       DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
986                i, fd_ptr->dev, fd_ptr->inode));
987       return fd_ptr;
988     }
989   }
990   DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
991 n"));
992   return 0;
993 }
994
995 /****************************************************************************
996 fd support routines - attempt to re-open an already open fd as O_RDWR.
997 Save the already open fd (we cannot close due to POSIX file locking braindamage.
998 ****************************************************************************/
999 static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
1000 {
1001   int fd = sys_open( fname, O_RDWR, mode);
1002
1003   if(fd == -1)
1004     return;
1005
1006   if(fd_ptr->real_open_flags == O_RDONLY)
1007     fd_ptr->fd_readonly = fd_ptr->fd;
1008   if(fd_ptr->real_open_flags == O_WRONLY)
1009     fd_ptr->fd_writeonly = fd_ptr->fd;
1010
1011   fd_ptr->fd = fd;
1012   fd_ptr->real_open_flags = O_RDWR;
1013 }
1014
1015 /****************************************************************************
1016 fd support routines - attempt to close the file referenced by this fd.
1017 Decrements the ref_count and returns it.
1018 ****************************************************************************/
1019 static int fd_attempt_close(file_fd_struct *fd_ptr)
1020 {
1021   DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
1022            fd_ptr - &FileFd[0],
1023            fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
1024            fd_ptr->real_open_flags,
1025            fd_ptr->ref_count));
1026   if(fd_ptr->ref_count > 0) {
1027     fd_ptr->ref_count--;
1028     if(fd_ptr->ref_count == 0) {
1029       if(fd_ptr->fd != -1)
1030         close(fd_ptr->fd);
1031       if(fd_ptr->fd_readonly != -1)
1032         close(fd_ptr->fd_readonly);
1033       if(fd_ptr->fd_writeonly != -1)
1034         close(fd_ptr->fd_writeonly);
1035       fd_ptr->fd = -1;
1036       fd_ptr->fd_readonly = -1;
1037       fd_ptr->fd_writeonly = -1;
1038       fd_ptr->real_open_flags = -1;
1039       fd_ptr->dev = (uint32)-1;
1040       fd_ptr->inode = (uint32)-1;
1041     }
1042   } 
1043  return fd_ptr->ref_count;
1044 }
1045
1046 /****************************************************************************
1047 open a file
1048 ****************************************************************************/
1049 static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
1050 {
1051   extern struct current_user current_user;
1052   pstring fname;
1053   struct stat statbuf;
1054   file_fd_struct *fd_ptr;
1055   files_struct *fsp = &Files[fnum];
1056
1057   fsp->open = False;
1058   fsp->fd_ptr = 0;
1059   fsp->granted_oplock = False;
1060   errno = EPERM;
1061
1062   pstrcpy(fname,fname1);
1063
1064   /* check permissions */
1065   if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
1066     {
1067       DEBUG(3,("Permission denied opening %s\n",fname));
1068       check_for_pipe(fname);
1069       return;
1070     }
1071
1072   /* this handles a bug in Win95 - it doesn't say to create the file when it 
1073      should */
1074   if (Connections[cnum].printer)
1075     flags |= O_CREAT;
1076
1077 /*
1078   if (flags == O_WRONLY)
1079     DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
1080 */
1081
1082 #if UTIME_WORKAROUND
1083   /* XXXX - is this OK?? */
1084   /* this works around a utime bug but can cause other problems */
1085   if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND))
1086     sys_unlink(fname);
1087 #endif
1088
1089   /*
1090    * Ensure we have a valid struct stat so we can search the
1091    * open fd table.
1092    */
1093   if(sbuf == 0) {
1094     if(stat(fname, &statbuf) < 0) {
1095       if(errno != ENOENT) {
1096         DEBUG(3,("Error doing stat on file %s (%s)\n",
1097                  fname,strerror(errno)));
1098
1099         check_for_pipe(fname);
1100         return;
1101       }
1102       sbuf = 0;
1103     } else {
1104       sbuf = &statbuf;
1105     }
1106   }
1107
1108   /*
1109    * Check to see if we have this file already
1110    * open. If we do, just use the already open fd and increment the
1111    * reference count (fd_get_already_open increments the ref_count).
1112    */
1113   if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
1114
1115     int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
1116
1117     /* File was already open. */
1118     if((flags & O_CREAT) && (flags & O_EXCL)) {
1119       fd_ptr->ref_count--;
1120       errno = EEXIST;
1121       return;
1122     }
1123
1124     /* 
1125      * If not opened O_RDWR try
1126      * and do that here - a chmod may have been done
1127      * between the last open and now. 
1128      */
1129     if(fd_ptr->real_open_flags != O_RDWR)
1130       fd_attempt_reopen(fname, mode, fd_ptr);
1131
1132     /*
1133      * Ensure that if we wanted write access
1134      * it has been opened for write, and if we wanted read it
1135      * was open for read. 
1136      */
1137     if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1138        ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1139        ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1140       DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1141                fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1142       check_for_pipe(fname);
1143       fd_ptr->ref_count--;
1144       return;
1145     }
1146
1147   } else {
1148     int open_flags;
1149     /* We need to allocate a new file_fd_struct (this increments the
1150        ref_count). */
1151     if((fd_ptr = fd_get_new()) == 0)
1152       return;
1153     /*
1154      * Whatever the requested flags, attempt read/write access,
1155      * as we don't know what flags future file opens may require.
1156      * If this fails, try again with the required flags. 
1157      * Even if we open read/write when only read access was 
1158      * requested the setting of the can_write flag in
1159      * the file_struct will protect us from errant
1160      * write requests. We never need to worry about O_APPEND
1161      * as this is not set anywhere in Samba.
1162      */
1163     fd_ptr->real_open_flags = O_RDWR;
1164     /* Set the flags as needed without the read/write modes. */
1165     open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1166     fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1167     /*
1168      * On some systems opening a file for R/W access on a read only
1169      * filesystems sets errno to EROFS.
1170      */
1171 #ifdef EROFS
1172     if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1173 #else /* No EROFS */
1174     if((fd_ptr->fd == -1) && (errno == EACCES)) {
1175 #endif /* EROFS */
1176       if(flags & O_WRONLY) {
1177         fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1178         fd_ptr->real_open_flags = O_WRONLY;
1179       } else {
1180         fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1181         fd_ptr->real_open_flags = O_RDONLY;
1182       }
1183     }
1184   }
1185
1186   if ((fd_ptr->fd >=0) && 
1187       Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1188     pstring dname;
1189     int dum1,dum2,dum3;
1190     char *p;
1191     pstrcpy(dname,fname);
1192     p = strrchr(dname,'/');
1193     if (p) *p = 0;
1194     if (sys_disk_free(dname,&dum1,&dum2,&dum3) < 
1195         lp_minprintspace(SNUM(cnum))) {
1196       fd_attempt_close(fd_ptr);
1197       fsp->fd_ptr = 0;
1198       if(fd_ptr->ref_count == 0)
1199         sys_unlink(fname);
1200       errno = ENOSPC;
1201       return;
1202     }
1203   }
1204     
1205   if (fd_ptr->fd < 0)
1206     {
1207       DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1208                fname,strerror(errno),flags));
1209       /* Ensure the ref_count is decremented. */
1210       fd_attempt_close(fd_ptr);
1211       check_for_pipe(fname);
1212       return;
1213     }
1214
1215   if (fd_ptr->fd >= 0)
1216     {
1217       if(sbuf == 0) {
1218         /* Do the fstat */
1219         if(fstat(fd_ptr->fd, &statbuf) == -1) {
1220           /* Error - backout !! */
1221           DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1222                    fd_ptr->fd, fname,strerror(errno)));
1223           /* Ensure the ref_count is decremented. */
1224           fd_attempt_close(fd_ptr);
1225           return;
1226         }
1227         sbuf = &statbuf;
1228       }
1229       /* Set the correct entries in fd_ptr. */
1230       fd_ptr->dev = (uint32)sbuf->st_dev;
1231       fd_ptr->inode = (uint32)sbuf->st_ino;
1232
1233       fsp->fd_ptr = fd_ptr;
1234       Connections[cnum].num_files_open++;
1235       fsp->mode = sbuf->st_mode;
1236       GetTimeOfDay(&fsp->open_time);
1237       fsp->uid = current_user.id;
1238       fsp->size = 0;
1239       fsp->pos = -1;
1240       fsp->open = True;
1241       fsp->mmap_ptr = NULL;
1242       fsp->mmap_size = 0;
1243       fsp->can_lock = True;
1244       fsp->can_read = ((flags & O_WRONLY)==0);
1245       fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1246       fsp->share_mode = 0;
1247       fsp->print_file = Connections[cnum].printer;
1248       fsp->modified = False;
1249       fsp->granted_oplock = False;
1250       fsp->cnum = cnum;
1251       string_set(&fsp->name,dos_to_unix(fname,False));
1252       fsp->wbmpx_ptr = NULL;      
1253
1254       /*
1255        * If the printer is marked as postscript output a leading
1256        * file identifier to ensure the file is treated as a raw
1257        * postscript file.
1258        * This has a similar effect as CtrlD=0 in WIN.INI file.
1259        * tim@fsg.com 09/06/94
1260        */
1261       if (fsp->print_file && POSTSCRIPT(cnum) && 
1262           fsp->can_write) 
1263         {
1264           DEBUG(3,("Writing postscript line\n"));
1265           write_file(fnum,"%!\n",3);
1266         }
1267       
1268       DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1269                timestring(),Connections[cnum].user,fname,
1270                BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write),
1271                Connections[cnum].num_files_open,fnum));
1272
1273     }
1274
1275 #if USE_MMAP
1276   /* mmap it if read-only */
1277   if (!fsp->can_write)
1278     {
1279       fsp->mmap_size = file_size(fname);
1280       fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size,
1281                                           PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0);
1282
1283       if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr)
1284         {
1285           DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1286           fsp->mmap_ptr = NULL;
1287         }
1288     }
1289 #endif
1290 }
1291
1292 /*******************************************************************
1293 sync a file
1294 ********************************************************************/
1295 void sync_file(int fnum)
1296 {
1297 #ifndef NO_FSYNC
1298   fsync(Files[fnum].fd_ptr->fd);
1299 #endif
1300 }
1301
1302 /****************************************************************************
1303 run a file if it is a magic script
1304 ****************************************************************************/
1305 static void check_magic(int fnum,int cnum)
1306 {
1307   if (!*lp_magicscript(SNUM(cnum)))
1308     return;
1309
1310   DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1311
1312   {
1313     char *p;
1314     if (!(p = strrchr(Files[fnum].name,'/')))
1315       p = Files[fnum].name;
1316     else
1317       p++;
1318
1319     if (!strequal(lp_magicscript(SNUM(cnum)),p))
1320       return;
1321   }
1322
1323   {
1324     int ret;
1325     pstring magic_output;
1326     pstring fname;
1327     pstrcpy(fname,Files[fnum].name);
1328
1329     if (*lp_magicoutput(SNUM(cnum)))
1330       pstrcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1331     else
1332       sprintf(magic_output,"%s.out",fname);
1333
1334     chmod(fname,0755);
1335     ret = smbrun(fname,magic_output,False);
1336     DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1337     unlink(fname);
1338   }
1339 }
1340
1341
1342 /****************************************************************************
1343 close a file - possibly invalidating the read prediction
1344 ****************************************************************************/
1345 void close_file(int fnum)
1346 {
1347   files_struct *fs_p = &Files[fnum];
1348   int cnum = fs_p->cnum;
1349   uint32 dev = fs_p->fd_ptr->dev;
1350   uint32 inode = fs_p->fd_ptr->inode;
1351   share_lock_token token;
1352
1353   invalidate_read_prediction(fs_p->fd_ptr->fd);
1354   fs_p->open = False;
1355   Connections[cnum].num_files_open--;
1356   if(fs_p->wbmpx_ptr) 
1357   {
1358     free((char *)fs_p->wbmpx_ptr);
1359     fs_p->wbmpx_ptr = NULL;
1360   }
1361
1362 #if USE_MMAP
1363   if(fs_p->mmap_ptr) 
1364   {
1365     munmap(fs_p->mmap_ptr,fs_p->mmap_size);
1366     fs_p->mmap_ptr = NULL;
1367   }
1368 #endif
1369
1370   if (lp_share_modes(SNUM(cnum)))
1371   {
1372     lock_share_entry( cnum, dev, inode, &token);
1373     del_share_mode(token, fnum);
1374   }
1375
1376   fd_attempt_close(fs_p->fd_ptr);
1377
1378   if (lp_share_modes(SNUM(cnum)))
1379     unlock_share_entry( cnum, dev, inode, token);
1380
1381   /* NT uses smbclose to start a print - weird */
1382   if (fs_p->print_file)
1383     print_file(fnum);
1384
1385   /* check for magic scripts */
1386   check_magic(fnum,cnum);
1387
1388   DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1389            timestring(),Connections[cnum].user,fs_p->name,
1390            Connections[cnum].num_files_open));
1391 }
1392
1393 enum {AFAIL,AREAD,AWRITE,AALL};
1394
1395 /*******************************************************************
1396 reproduce the share mode access table
1397 ********************************************************************/
1398 static int access_table(int new_deny,int old_deny,int old_mode,
1399                         int share_pid,char *fname)
1400 {
1401   if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1402
1403   if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1404     int pid = getpid();
1405     if (old_deny == new_deny && share_pid == pid) 
1406         return(AALL);    
1407
1408     if (old_mode == 0) return(AREAD);
1409
1410     /* the new smbpub.zip spec says that if the file extension is
1411        .com, .dll, .exe or .sym then allow the open. I will force
1412        it to read-only as this seems sensible although the spec is
1413        a little unclear on this. */
1414     if ((fname = strrchr(fname,'.'))) {
1415       if (strequal(fname,".com") ||
1416           strequal(fname,".dll") ||
1417           strequal(fname,".exe") ||
1418           strequal(fname,".sym"))
1419         return(AREAD);
1420     }
1421
1422     return(AFAIL);
1423   }
1424
1425   switch (new_deny) 
1426     {
1427     case DENY_WRITE:
1428       if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1429       if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1430       if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1431       return(AFAIL);
1432     case DENY_READ:
1433       if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1434       if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1435       if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1436       return(AFAIL);
1437     case DENY_NONE:
1438       if (old_deny==DENY_WRITE) return(AREAD);
1439       if (old_deny==DENY_READ) return(AWRITE);
1440       if (old_deny==DENY_NONE) return(AALL);
1441       return(AFAIL);      
1442     }
1443   return(AFAIL);      
1444 }
1445
1446 /*******************************************************************
1447 check if the share mode on a file allows it to be deleted or unlinked
1448 return True if sharing doesn't prevent the operation
1449 ********************************************************************/
1450 BOOL check_file_sharing(int cnum,char *fname)
1451 {
1452   int i;
1453   int ret = False;
1454   min_share_mode_entry *old_shares = 0;
1455   int num_share_modes;
1456   struct stat sbuf;
1457   share_lock_token token;
1458   int pid = getpid();
1459   uint32 dev, inode;
1460
1461   if(!lp_share_modes(SNUM(cnum)))
1462     return True;
1463
1464   if (stat(fname,&sbuf) == -1) return(True);
1465
1466   dev = (uint32)sbuf.st_dev;
1467   inode = (uint32)sbuf.st_ino;
1468
1469   lock_share_entry(cnum, dev, inode, &token);
1470   num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
1471
1472   /*
1473    * Check if the share modes will give us access.
1474    */
1475
1476   if(num_share_modes != 0)
1477   {
1478     BOOL broke_oplock;
1479
1480     do
1481     {
1482
1483       broke_oplock = False;
1484       for(i = 0; i < num_share_modes; i++)
1485       {
1486         min_share_mode_entry *share_entry = &old_shares[i];
1487
1488         /* 
1489          * Break oplocks before checking share modes. See comment in
1490          * open_file_shared for details. 
1491          * Check if someone has an oplock on this file. If so we must 
1492          * break it before continuing. 
1493          */
1494         if(share_entry->op_type & BATCH_OPLOCK)
1495         {
1496
1497           DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \
1498 dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode));
1499
1500           /* Oplock break.... */
1501           unlock_share_entry(cnum, dev, inode, token);
1502           if(request_oplock_break(share_entry, dev, inode) == False)
1503           {
1504             free((char *)old_shares);
1505             DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \
1506 dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
1507             return False;
1508           }
1509           lock_share_entry(cnum, dev, inode, &token);
1510           broke_oplock = True;
1511           break;
1512         }
1513
1514         /* someone else has a share lock on it, check to see 
1515            if we can too */
1516         if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid))
1517           goto free_and_exit;
1518
1519       } /* end for */
1520
1521       if(broke_oplock)
1522       {
1523         free((char *)old_shares);
1524         num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
1525       }
1526     } while(broke_oplock);
1527   }
1528
1529   /* XXXX exactly what share mode combinations should be allowed for
1530      deleting/renaming? */
1531   /* If we got here then either there were no share modes or
1532      all share modes were DENY_DOS and the pid == getpid() */
1533   ret = True;
1534
1535 free_and_exit:
1536
1537   unlock_share_entry(cnum, dev, inode, token);
1538   if(old_shares != NULL)
1539     free((char *)old_shares);
1540   return(ret);
1541 }
1542
1543 /****************************************************************************
1544   C. Hoch 11/22/95
1545   Helper for open_file_shared. 
1546   Truncate a file after checking locking; close file if locked.
1547   **************************************************************************/
1548 static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, 
1549        BOOL *share_locked)
1550 {
1551   if (Files[fnum].can_write){
1552     if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1553       /* If share modes are in force for this connection we
1554          have the share entry locked. Unlock it before closing. */
1555       if (*share_locked && lp_share_modes(SNUM(cnum)))
1556         unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, 
1557                             Files[fnum].fd_ptr->inode, token);
1558       close_file(fnum);   
1559       /* Share mode no longer locked. */
1560       *share_locked = False;
1561       errno = EACCES;
1562       unix_ERR_class = ERRDOS;
1563       unix_ERR_code = ERRlock;
1564     }
1565     else
1566       ftruncate(Files[fnum].fd_ptr->fd,0); 
1567   }
1568 }
1569
1570 /****************************************************************************
1571 check if we can open a file with a share mode
1572 ****************************************************************************/
1573 int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname,
1574                       BOOL fcbopen, int *flags)
1575 {
1576   int old_open_mode = share->share_mode &0xF;
1577   int old_deny_mode = (share->share_mode >>4)&7;
1578
1579   if (old_deny_mode > 4 || old_open_mode > 2)
1580   {
1581     DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
1582                deny_mode,old_deny_mode,old_open_mode,fname));
1583     return False;
1584   }
1585
1586   {
1587     int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1588                                 share->pid,fname);
1589
1590     if ((access_allowed == AFAIL) ||
1591         (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) ||
1592         (access_allowed == AREAD && *flags == O_WRONLY) ||
1593         (access_allowed == AWRITE && *flags == O_RDONLY))
1594     {
1595       DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1596                 deny_mode,old_deny_mode,old_open_mode,
1597                 share->pid,fname, access_allowed));
1598       return False;
1599     }
1600
1601     if (access_allowed == AREAD)
1602       *flags = O_RDONLY;
1603
1604     if (access_allowed == AWRITE)
1605       *flags = O_WRONLY;
1606
1607   }
1608   return True;
1609 }
1610
1611 /****************************************************************************
1612 open a file with a share mode
1613 ****************************************************************************/
1614 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1615                       int mode,int oplock_request, int *Access,int *action)
1616 {
1617   files_struct *fs_p = &Files[fnum];
1618   int flags=0;
1619   int flags2=0;
1620   int deny_mode = (share_mode>>4)&7;
1621   struct stat sbuf;
1622   BOOL file_existed = file_exist(fname,&sbuf);
1623   BOOL share_locked = False;
1624   BOOL fcbopen = False;
1625   share_lock_token token;
1626   uint32 dev = 0;
1627   uint32 inode = 0;
1628   int num_share_modes = 0;
1629
1630   fs_p->open = False;
1631   fs_p->fd_ptr = 0;
1632
1633   /* this is for OS/2 EAs - try and say we don't support them */
1634   if (strstr(fname,".+,;=[].")) 
1635   {
1636     unix_ERR_class = ERRDOS;
1637     /* OS/2 Workplace shell fix may be main code stream in a later release. */ 
1638 #ifdef OS2_WPS_FIX
1639     unix_ERR_code = ERRcannotopen;
1640 #else /* OS2_WPS_FIX */
1641     unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1642 #endif /* OS2_WPS_FIX */
1643
1644     return;
1645   }
1646
1647   if ((ofun & 0x3) == 0 && file_existed)  
1648   {
1649     errno = EEXIST;
1650     return;
1651   }
1652       
1653   if (ofun & 0x10)
1654     flags2 |= O_CREAT;
1655   if ((ofun & 0x3) == 2)
1656     flags2 |= O_TRUNC;
1657
1658   /* note that we ignore the append flag as 
1659      append does not mean the same thing under dos and unix */
1660
1661   switch (share_mode&0xF)
1662   {
1663     case 1: 
1664       flags = O_WRONLY; 
1665       break;
1666     case 0xF: 
1667       fcbopen = True;
1668       flags = O_RDWR; 
1669       break;
1670     case 2: 
1671       flags = O_RDWR; 
1672       break;
1673     default:
1674       flags = O_RDONLY;
1675       break;
1676   }
1677   
1678   if (flags != O_RDONLY && file_existed && 
1679       (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) 
1680   {
1681     if (!fcbopen) 
1682     {
1683       errno = EACCES;
1684       return;
1685     }
1686     flags = O_RDONLY;
1687   }
1688
1689   if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) 
1690   {
1691     DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1692     errno = EINVAL;
1693     return;
1694   }
1695
1696   if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1697
1698   if (lp_share_modes(SNUM(cnum))) 
1699   {
1700     int i;
1701     min_share_mode_entry *old_shares = 0;
1702
1703     if (file_existed)
1704     {
1705       dev = (uint32)sbuf.st_dev;
1706       inode = (uint32)sbuf.st_ino;
1707       lock_share_entry(cnum, dev, inode, &token);
1708       share_locked = True;
1709       num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
1710     }
1711
1712     /*
1713      * Check if the share modes will give us access.
1714      */
1715
1716     if(share_locked && (num_share_modes != 0))
1717     {
1718       BOOL broke_oplock;
1719
1720       do
1721       {
1722
1723         broke_oplock = False;
1724         for(i = 0; i < num_share_modes; i++)
1725         {
1726           min_share_mode_entry *share_entry = &old_shares[i];
1727
1728           /* 
1729            * By observation of NetBench, oplocks are broken *before* share
1730            * modes are checked. This allows a file to be closed by the client
1731            * if the share mode would deny access and the client has an oplock. 
1732            * Check if someone has an oplock on this file. If so we must break 
1733            * it before continuing. 
1734            */
1735           if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
1736           {
1737
1738             DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \
1739 dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode));
1740
1741             /* Oplock break.... */
1742             unlock_share_entry(cnum, dev, inode, token);
1743             if(request_oplock_break(share_entry, dev, inode) == False)
1744             {
1745               free((char *)old_shares);
1746               DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \
1747 dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
1748               errno = EACCES;
1749               unix_ERR_class = ERRDOS;
1750               unix_ERR_code = ERRbadshare;
1751               return;
1752             }
1753             lock_share_entry(cnum, dev, inode, &token);
1754             broke_oplock = True;
1755             break;
1756           }
1757
1758           /* someone else has a share lock on it, check to see 
1759              if we can too */
1760           if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False)
1761           {
1762             free((char *)old_shares);
1763             unlock_share_entry(cnum, dev, inode, token);
1764             errno = EACCES;
1765             unix_ERR_class = ERRDOS;
1766             unix_ERR_code = ERRbadshare;
1767             return;
1768           }
1769
1770         } /* end for */
1771
1772         if(broke_oplock)
1773         {
1774           free((char *)old_shares);
1775           num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
1776         }
1777       } while(broke_oplock);
1778     }
1779
1780     if(old_shares != 0)
1781       free((char *)old_shares);
1782   }
1783
1784   DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1785            flags,flags2,mode));
1786
1787   open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1788   if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen) 
1789   {
1790     flags = O_RDONLY;
1791     open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1792   }
1793
1794   if (fs_p->open) 
1795   {
1796     int open_mode=0;
1797
1798     if((share_locked == False) && lp_share_modes(SNUM(cnum)))
1799     {
1800       /* We created the file - thus we must now lock the share entry before creating it. */
1801       dev = fs_p->fd_ptr->dev;
1802       inode = fs_p->fd_ptr->inode;
1803       lock_share_entry(cnum, dev, inode, &token);
1804       share_locked = True;
1805     }
1806
1807     switch (flags) 
1808     {
1809       case O_RDONLY:
1810         open_mode = 0;
1811         break;
1812       case O_RDWR:
1813         open_mode = 2;
1814         break;
1815       case O_WRONLY:
1816         open_mode = 1;
1817         break;
1818     }
1819
1820     fs_p->share_mode = (deny_mode<<4) | open_mode;
1821
1822     if (Access)
1823       (*Access) = open_mode;
1824
1825     if (action) 
1826     {
1827       if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1828       if (!file_existed) *action = 2;
1829       if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1830     }
1831     /* We must create the share mode entry before truncate as
1832        truncate can fail due to locking and have to close the
1833        file (which expects the share_mode_entry to be there).
1834      */
1835     if (lp_share_modes(SNUM(cnum)))
1836     {
1837       uint16 port = 0;
1838       /* JRA. Currently this only services Exlcusive and batch
1839          oplocks (no other opens on this file). This needs to
1840          be extended to level II oplocks (multiple reader
1841          oplocks). */
1842
1843       if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum)))
1844       {
1845         fs_p->granted_oplock = True;
1846         global_oplocks_open++;
1847         port = oplock_port;
1848
1849         DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \
1850 dev = %x, inode = %x\n", oplock_request, fname, dev, inode));
1851
1852       }
1853       else
1854       {
1855         port = 0;
1856         oplock_request = 0;
1857       }
1858       set_share_mode(token, fnum, port, oplock_request);
1859     }
1860
1861     if ((flags2&O_TRUNC) && file_existed)
1862       truncate_unless_locked(fnum,cnum,token,&share_locked);
1863   }
1864
1865   if (share_locked && lp_share_modes(SNUM(cnum)))
1866     unlock_share_entry( cnum, dev, inode, token);
1867 }
1868
1869 /****************************************************************************
1870 seek a file. Try to avoid the seek if possible
1871 ****************************************************************************/
1872 int seek_file(int fnum,uint32 pos)
1873 {
1874   uint32 offset = 0;
1875   if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1876     offset = 3;
1877
1878   Files[fnum].pos = (int)(lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) 
1879                                   - offset);
1880   return(Files[fnum].pos);
1881 }
1882
1883 /****************************************************************************
1884 read from a file
1885 ****************************************************************************/
1886 int read_file(int fnum,char *data,uint32 pos,int n)
1887 {
1888   int ret=0,readret;
1889
1890   if (!Files[fnum].can_write)
1891     {
1892       ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1893
1894       data += ret;
1895       n -= ret;
1896       pos += ret;
1897     }
1898
1899 #if USE_MMAP
1900   if (Files[fnum].mmap_ptr)
1901     {
1902       int num = MIN(n,(int)(Files[fnum].mmap_size-pos));
1903       if (num > 0)
1904         {
1905           memcpy(data,Files[fnum].mmap_ptr+pos,num);
1906           data += num;
1907           pos += num;
1908           n -= num;
1909           ret += num;
1910         }
1911     }
1912 #endif
1913
1914   if (n <= 0)
1915     return(ret);
1916
1917   if (seek_file(fnum,pos) != pos)
1918     {
1919       DEBUG(3,("Failed to seek to %d\n",pos));
1920       return(ret);
1921     }
1922   
1923   if (n > 0) {
1924     readret = read(Files[fnum].fd_ptr->fd,data,n);
1925     if (readret > 0) ret += readret;
1926   }
1927
1928   return(ret);
1929 }
1930
1931
1932 /****************************************************************************
1933 write to a file
1934 ****************************************************************************/
1935 int write_file(int fnum,char *data,int n)
1936 {
1937   if (!Files[fnum].can_write) {
1938     errno = EPERM;
1939     return(0);
1940   }
1941
1942   if (!Files[fnum].modified) {
1943     struct stat st;
1944     Files[fnum].modified = True;
1945     if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
1946       int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
1947       if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {  
1948         dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
1949       }
1950     }  
1951   }
1952
1953   return(write_data(Files[fnum].fd_ptr->fd,data,n));
1954 }
1955
1956
1957 /****************************************************************************
1958 load parameters specific to a connection/service
1959 ****************************************************************************/
1960 BOOL become_service(int cnum,BOOL do_chdir)
1961 {
1962   extern char magic_char;
1963   static int last_cnum = -1;
1964   int snum;
1965
1966   if (!OPEN_CNUM(cnum))
1967     {
1968       last_cnum = -1;
1969       return(False);
1970     }
1971
1972   Connections[cnum].lastused = smb_last_time;
1973
1974   snum = SNUM(cnum);
1975   
1976   if (do_chdir &&
1977       ChDir(Connections[cnum].connectpath) != 0 &&
1978       ChDir(Connections[cnum].origpath) != 0)
1979     {
1980       DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
1981             Connections[cnum].connectpath,cnum));     
1982       return(False);
1983     }
1984
1985   if (cnum == last_cnum)
1986     return(True);
1987
1988   last_cnum = cnum;
1989
1990   case_default = lp_defaultcase(snum);
1991   case_preserve = lp_preservecase(snum);
1992   short_case_preserve = lp_shortpreservecase(snum);
1993   case_mangle = lp_casemangle(snum);
1994   case_sensitive = lp_casesensitive(snum);
1995   magic_char = lp_magicchar(snum);
1996   use_mangled_map = (*lp_mangled_map(snum) ? True:False);
1997   return(True);
1998 }
1999
2000
2001 /****************************************************************************
2002   find a service entry
2003 ****************************************************************************/
2004 int find_service(char *service)
2005 {
2006    int iService;
2007
2008    string_sub(service,"\\","/");
2009
2010    iService = lp_servicenumber(service);
2011
2012    /* now handle the special case of a home directory */
2013    if (iService < 0)
2014    {
2015       char *phome_dir = get_home_dir(service);
2016       DEBUG(3,("checking for home directory %s gave %s\n",service,
2017             phome_dir?phome_dir:"(NULL)"));
2018       if (phome_dir)
2019       {   
2020          int iHomeService;
2021          if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
2022          {
2023             lp_add_home(service,iHomeService,phome_dir);
2024             iService = lp_servicenumber(service);
2025          }
2026       }
2027    }
2028
2029    /* If we still don't have a service, attempt to add it as a printer. */
2030    if (iService < 0)
2031    {
2032       int iPrinterService;
2033
2034       if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
2035       {
2036          char *pszTemp;
2037
2038          DEBUG(3,("checking whether %s is a valid printer name...\n", service));
2039          pszTemp = PRINTCAP;
2040          if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
2041          {
2042             DEBUG(3,("%s is a valid printer name\n", service));
2043             DEBUG(3,("adding %s as a printer service\n", service));
2044             lp_add_printer(service,iPrinterService);
2045             iService = lp_servicenumber(service);
2046             if (iService < 0)
2047                DEBUG(0,("failed to add %s as a printer service!\n", service));
2048          }
2049          else
2050             DEBUG(3,("%s is not a valid printer name\n", service));
2051       }
2052    }
2053
2054    /* just possibly it's a default service? */
2055    if (iService < 0) 
2056      {
2057        char *defservice = lp_defaultservice();
2058        if (defservice && *defservice && !strequal(defservice,service)) {
2059          iService = find_service(defservice);
2060          if (iService >= 0) {
2061            string_sub(service,"_","/");
2062            iService = lp_add_service(service,iService);
2063          }
2064        }
2065      }
2066
2067    if (iService >= 0)
2068       if (!VALID_SNUM(iService))
2069       {
2070          DEBUG(0,("Invalid snum %d for %s\n",iService,service));
2071          iService = -1;
2072       }
2073
2074    if (iService < 0)
2075       DEBUG(3,("find_service() failed to find service %s\n", service));
2076
2077    return (iService);
2078 }
2079
2080
2081 /****************************************************************************
2082   create an error packet from a cached error.
2083 ****************************************************************************/
2084 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
2085 {
2086   write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
2087
2088   int32 eclass = wbmpx->wr_errclass;
2089   int32 err = wbmpx->wr_error;
2090
2091   /* We can now delete the auxiliary struct */
2092   free((char *)wbmpx);
2093   Files[fnum].wbmpx_ptr = NULL;
2094   return error_packet(inbuf,outbuf,eclass,err,line);
2095 }
2096
2097
2098 struct
2099 {
2100   int unixerror;
2101   int smbclass;
2102   int smbcode;
2103 } unix_smb_errmap[] =
2104 {
2105   {EPERM,ERRDOS,ERRnoaccess},
2106   {EACCES,ERRDOS,ERRnoaccess},
2107   {ENOENT,ERRDOS,ERRbadfile},
2108   {ENOTDIR,ERRDOS,ERRbadpath},
2109   {EIO,ERRHRD,ERRgeneral},
2110   {EBADF,ERRSRV,ERRsrverror},
2111   {EINVAL,ERRSRV,ERRsrverror},
2112   {EEXIST,ERRDOS,ERRfilexists},
2113   {ENFILE,ERRDOS,ERRnofids},
2114   {EMFILE,ERRDOS,ERRnofids},
2115   {ENOSPC,ERRHRD,ERRdiskfull},
2116 #ifdef EDQUOT
2117   {EDQUOT,ERRHRD,ERRdiskfull},
2118 #endif
2119 #ifdef ENOTEMPTY
2120   {ENOTEMPTY,ERRDOS,ERRnoaccess},
2121 #endif
2122 #ifdef EXDEV
2123   {EXDEV,ERRDOS,ERRdiffdevice},
2124 #endif
2125   {EROFS,ERRHRD,ERRnowrite},
2126   {0,0,0}
2127 };
2128
2129 /****************************************************************************
2130   create an error packet from errno
2131 ****************************************************************************/
2132 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
2133 {
2134   int eclass=def_class;
2135   int ecode=def_code;
2136   int i=0;
2137
2138   if (unix_ERR_class != SUCCESS)
2139     {
2140       eclass = unix_ERR_class;
2141       ecode = unix_ERR_code;
2142       unix_ERR_class = SUCCESS;
2143       unix_ERR_code = 0;
2144     }
2145   else
2146     {
2147       while (unix_smb_errmap[i].smbclass != 0)
2148       {
2149             if (unix_smb_errmap[i].unixerror == errno)
2150             {
2151               eclass = unix_smb_errmap[i].smbclass;
2152               ecode = unix_smb_errmap[i].smbcode;
2153               break;
2154             }
2155           i++;
2156       }
2157     }
2158
2159   return(error_packet(inbuf,outbuf,eclass,ecode,line));
2160 }
2161
2162
2163 /****************************************************************************
2164   create an error packet. Normally called using the ERROR() macro
2165 ****************************************************************************/
2166 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
2167 {
2168   int outsize = set_message(outbuf,0,0,True);
2169   int cmd;
2170   cmd = CVAL(inbuf,smb_com);
2171   
2172   CVAL(outbuf,smb_rcls) = error_class;
2173   SSVAL(outbuf,smb_err,error_code);  
2174   
2175   DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
2176            timestring(),
2177            line,
2178            (int)CVAL(inbuf,smb_com),
2179            smb_fn_name(CVAL(inbuf,smb_com)),
2180            error_class,
2181            error_code));
2182
2183   if (errno != 0)
2184     DEBUG(3,("error string = %s\n",strerror(errno)));
2185   
2186   return(outsize);
2187 }
2188
2189
2190 #ifndef SIGCLD_IGNORE
2191 /****************************************************************************
2192 this prevents zombie child processes
2193 ****************************************************************************/
2194 static int sig_cld()
2195 {
2196   static int depth = 0;
2197   if (depth != 0)
2198     {
2199       DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2200       depth=0;
2201       return(0);
2202     }
2203   depth++;
2204
2205   BlockSignals(True,SIGCLD);
2206   DEBUG(5,("got SIGCLD\n"));
2207
2208 #ifdef USE_WAITPID
2209   while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2210 #endif
2211
2212   /* Stop zombies */
2213   /* Stevens, Adv. Unix Prog. says that on system V you must call
2214      wait before reinstalling the signal handler, because the kernel
2215      calls the handler from within the signal-call when there is a
2216      child that has exited. This would lead to an infinite recursion
2217      if done vice versa. */
2218         
2219 #ifndef DONT_REINSTALL_SIG
2220 #ifdef SIGCLD_IGNORE
2221   signal(SIGCLD, SIG_IGN);  
2222 #else
2223   signal(SIGCLD, SIGNAL_CAST sig_cld);
2224 #endif
2225 #endif
2226
2227 #ifndef USE_WAITPID
2228   while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
2229 #endif
2230   depth--;
2231   BlockSignals(False,SIGCLD);
2232   return 0;
2233 }
2234 #endif
2235
2236 /****************************************************************************
2237   this is called when the client exits abruptly
2238   **************************************************************************/
2239 static int sig_pipe()
2240 {
2241   extern int password_client;
2242   BlockSignals(True,SIGPIPE);
2243
2244   if (password_client != -1) {
2245     DEBUG(3,("lost connection to password server\n"));
2246     close(password_client);
2247     password_client = -1;
2248 #ifndef DONT_REINSTALL_SIG
2249     signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2250 #endif
2251     BlockSignals(False,SIGPIPE);
2252     return 0;
2253   }
2254
2255   exit_server("Got sigpipe\n");
2256   return(0);
2257 }
2258
2259 /****************************************************************************
2260   open the socket communication
2261 ****************************************************************************/
2262 static BOOL open_sockets(BOOL is_daemon,int port)
2263 {
2264   extern int Client;
2265
2266   if (is_daemon)
2267     {
2268       int s;
2269       struct sockaddr addr;
2270       int in_addrlen = sizeof(addr);
2271        
2272       /* Stop zombies */
2273 #ifdef SIGCLD_IGNORE
2274       signal(SIGCLD, SIG_IGN);
2275 #else
2276       signal(SIGCLD, SIGNAL_CAST sig_cld);
2277 #endif
2278
2279       /* open an incoming socket */
2280       s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
2281       if (s == -1)
2282         return(False);
2283
2284       /* ready to listen */
2285       if (listen(s, 5) == -1) 
2286         {
2287           DEBUG(0,("listen: %s\n",strerror(errno)));
2288           close(s);
2289           return False;
2290         }
2291       
2292       if(atexit_set == 0)
2293         atexit(killkids);
2294
2295       /* now accept incoming connections - forking a new process
2296          for each incoming connection */
2297       DEBUG(2,("waiting for a connection\n"));
2298       while (1)
2299         {
2300           Client = accept(s,&addr,&in_addrlen);
2301
2302           if (Client == -1 && errno == EINTR)
2303             continue;
2304
2305           if (Client == -1)
2306             {
2307               DEBUG(0,("accept: %s\n",strerror(errno)));
2308               continue;
2309             }
2310
2311 #ifdef NO_FORK_DEBUG
2312 #ifndef NO_SIGNAL_TEST
2313           signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2314           signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2315 #endif
2316           return True;
2317 #else
2318           if (Client != -1 && fork()==0)
2319             {
2320               /* Child code ... */
2321 #ifndef NO_SIGNAL_TEST
2322               signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2323               signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2324 #endif
2325               /* close the listening socket */
2326               close(s);
2327
2328               /* close our standard file descriptors */
2329               close_low_fds();
2330               am_parent = 0;
2331   
2332               set_socket_options(Client,"SO_KEEPALIVE");
2333               set_socket_options(Client,user_socket_options);
2334
2335               /* Reset global variables in util.c so that
2336                  client substitutions will be done correctly
2337                  in the process.
2338                */
2339               reset_globals_after_fork();
2340               return True; 
2341             }
2342           close(Client); /* The parent doesn't need this socket */
2343 #endif
2344         }
2345     }
2346   else
2347     {
2348       /* We will abort gracefully when the client or remote system 
2349          goes away */
2350 #ifndef NO_SIGNAL_TEST
2351       signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2352 #endif
2353       Client = dup(0);
2354
2355       /* close our standard file descriptors */
2356       close_low_fds();
2357
2358       set_socket_options(Client,"SO_KEEPALIVE");
2359       set_socket_options(Client,user_socket_options);
2360     }
2361
2362   return True;
2363 }
2364
2365 /****************************************************************************
2366   process an smb from the client - split out from the process() code so
2367   it can be used by the oplock break code.
2368 ****************************************************************************/
2369
2370 static void process_smb(char *inbuf, char *outbuf)
2371 {
2372   extern int Client;
2373   static int trans_num;
2374   int msg_type = CVAL(inbuf,0);
2375   int32 len = smb_len(inbuf);
2376   int nread = len + 4;
2377
2378   if (trans_num == 0) {
2379           /* on the first packet, check the global hosts allow/ hosts
2380              deny parameters before doing any parsing of the packet
2381              passed to us by the client.  This prevents attacks on our
2382              parsing code from hosts not in the hosts allow list */
2383           if (!check_access(-1)) {
2384                   /* send a negative session response "not listining on calling
2385                    name" */
2386                   static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
2387                   DEBUG(1,("%s Connection denied from %s\n",
2388                            timestring(),client_addr()));
2389                   send_smb(Client,(char *)buf);
2390                   exit_server("connection denied");
2391           }
2392   }
2393
2394   DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
2395   DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
2396
2397 #ifdef WITH_VTP
2398   if(trans_num == 1 && VT_Check(inbuf)) 
2399   {
2400     VT_Process();
2401     return;
2402   }
2403 #endif
2404
2405   if (msg_type == 0)
2406     show_msg(inbuf);
2407
2408   nread = construct_reply(inbuf,outbuf,nread,max_send);
2409       
2410   if(nread > 0) 
2411   {
2412     if (CVAL(outbuf,0) == 0)
2413       show_msg(outbuf);
2414         
2415     if (nread != smb_len(outbuf) + 4) 
2416     {
2417       DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
2418                  nread, smb_len(outbuf)));
2419     }
2420     else
2421       send_smb(Client,outbuf);
2422   }
2423   trans_num++;
2424 }
2425
2426 /****************************************************************************
2427   open the oplock IPC socket communication
2428 ****************************************************************************/
2429 static BOOL open_oplock_ipc()
2430 {
2431   struct sockaddr_in sock_name;
2432   int len = sizeof(sock_name);
2433
2434   DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n"));
2435
2436   /* Open a lookback UDP socket on a random port. */
2437   oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK));
2438   if (oplock_sock == -1)
2439   {
2440     DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \
2441 address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno)));
2442     oplock_port = 0;
2443     return(False);
2444   }
2445
2446   /* Find out the transient UDP port we have been allocated. */
2447   if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0)
2448   {
2449     DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n",
2450             strerror(errno)));
2451     close(oplock_sock);
2452     oplock_sock = -1;
2453     oplock_port = 0;
2454     return False;
2455   }
2456   oplock_port = ntohs(sock_name.sin_port);
2457
2458   DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", 
2459             getpid(), oplock_port));
2460
2461   return True;
2462 }
2463
2464 /****************************************************************************
2465   process an oplock break message.
2466 ****************************************************************************/
2467 static BOOL process_local_message(int sock, char *buffer, int buf_size)
2468 {
2469   int32 msg_len;
2470   int16 from_port;
2471   char *msg_start;
2472
2473   msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET);
2474   from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET);
2475
2476   msg_start = &buffer[UDP_CMD_HEADER_LEN];
2477
2478   DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", 
2479             msg_len, from_port));
2480
2481   /* Switch on message command - currently OPLOCK_BREAK_CMD is the
2482      only valid request. */
2483
2484   switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET))
2485   {
2486     case OPLOCK_BREAK_CMD:
2487       /* Ensure that the msg length is correct. */
2488       if(msg_len != OPLOCK_BREAK_MSG_LEN)
2489       {
2490         DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, \
2491 should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
2492         return False;
2493       }
2494       {
2495         uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
2496         uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
2497         uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
2498         struct timeval tval;
2499         struct sockaddr_in toaddr;
2500
2501         tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET);
2502         tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET);
2503
2504         DEBUG(5,("process_local_message: oplock break request from \
2505 pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
2506
2507         /*
2508          * If we have no record of any currently open oplocks,
2509          * it's not an error, as a close command may have
2510          * just been issued on the file that was oplocked.
2511          * Just return success in this case.
2512          */
2513
2514         if(global_oplocks_open != 0)
2515         {
2516           if(oplock_break(dev, inode, &tval) == False)
2517           {
2518             DEBUG(0,("process_local_message: oplock break failed - \
2519 not returning udp message.\n"));
2520             return False;
2521           }
2522         }
2523         else
2524         {
2525           DEBUG(3,("process_local_message: oplock break requested with no outstanding \
2526 oplocks. Returning success.\n"));
2527         }
2528
2529         /* Send the message back after OR'ing in the 'REPLY' bit. */
2530         SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY);
2531   
2532         bzero((char *)&toaddr,sizeof(toaddr));
2533         toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2534         toaddr.sin_port = htons(from_port);
2535         toaddr.sin_family = AF_INET;
2536
2537         if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
2538                 (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) 
2539         {
2540           DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n",
2541                     remotepid, strerror(errno)));
2542           return False;
2543         }
2544
2545         DEBUG(5,("process_local_message: oplock break reply sent to \
2546 pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, 
2547                 from_port, dev, inode));
2548
2549       }
2550       break;
2551     /* 
2552      * Keep this as a debug case - eventually we can remove it.
2553      */
2554     case 0x8001:
2555       DEBUG(0,("process_local_message: Received unsolicited break \
2556 reply - dumping info.\n"));
2557
2558       if(msg_len != OPLOCK_BREAK_MSG_LEN)
2559       {
2560         DEBUG(0,("process_local_message: ubr: incorrect length for reply \
2561 (was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
2562         return False;
2563       }
2564
2565       {
2566         uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
2567         uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
2568         uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
2569
2570         DEBUG(0,("process_local_message: unsolicited oplock break reply from \
2571 pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
2572
2573        }
2574        return False;
2575
2576     default:
2577       DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n",
2578                 (unsigned int)SVAL(msg_start,0)));
2579       return False;
2580   }
2581   return True;
2582 }
2583
2584 /****************************************************************************
2585  Process an oplock break directly.
2586 ****************************************************************************/
2587 BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval)
2588 {
2589   extern int Client;
2590   static char *inbuf = NULL;
2591   static char *outbuf = NULL;
2592   files_struct *fsp = NULL;
2593   int fnum;
2594   time_t start_time;
2595   BOOL shutdown_server = False;
2596
2597   DEBUG(5,("oplock_break: called for dev = %x, inode = %x. Current \
2598 global_oplocks_open = %d\n", dev, inode, global_oplocks_open));
2599
2600   if(inbuf == NULL)
2601   {
2602     inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2603     if(inbuf == NULL) {
2604       DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
2605       return False;
2606     } 
2607     outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2608     if(outbuf == NULL) {
2609       DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
2610       free(inbuf);
2611       inbuf = NULL;
2612       return False;
2613     }
2614   } 
2615
2616   /* We need to search the file open table for the
2617      entry containing this dev and inode, and ensure
2618      we have an oplock on it. */
2619   for( fnum = 0; fnum < MAX_OPEN_FILES; fnum++)
2620   {
2621     if(OPEN_FNUM(fnum))
2622     {
2623       fsp = &Files[fnum];
2624       if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode) &&
2625          (fsp->open_time.tv_sec == tval->tv_sec) && 
2626          (fsp->open_time.tv_usec == tval->tv_usec))
2627         break;
2628     }
2629   }
2630
2631   if(fsp == NULL)
2632   {
2633     /* The file could have been closed in the meantime - return success. */
2634     DEBUG(3,("oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \
2635 allowing break to succeed.\n", dev, inode, fnum));
2636     return True;
2637   }
2638
2639   /* Ensure we have an oplock on the file */
2640
2641   /* There is a potential race condition in that an oplock could
2642      have been broken due to another udp request, and yet there are
2643      still oplock break messages being sent in the udp message
2644      queue for this file. So return true if we don't have an oplock,
2645      as we may have just freed it.
2646    */
2647
2648   if(!fsp->granted_oplock)
2649   {
2650     DEBUG(3,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \
2651 Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode));
2652     return True;
2653   }
2654
2655   /* Now comes the horrid part. We must send an oplock break to the client,
2656      and then process incoming messages until we get a close or oplock release.
2657    */
2658
2659   /* Prepare the SMBlockingX message. */
2660   bzero(outbuf,smb_size);
2661   set_message(outbuf,8,0,True);
2662
2663   SCVAL(outbuf,smb_com,SMBlockingX);
2664   SSVAL(outbuf,smb_tid,fsp->cnum);
2665   SSVAL(outbuf,smb_pid,0xFFFF);
2666   SSVAL(outbuf,smb_uid,0);
2667   SSVAL(outbuf,smb_mid,0xFFFF);
2668   SCVAL(outbuf,smb_vwv0,0xFF);
2669   SSVAL(outbuf,smb_vwv2,fnum);
2670   SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE);
2671   /* Change this when we have level II oplocks. */
2672   SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE);
2673  
2674   send_smb(Client, outbuf);
2675
2676   global_oplock_break = True;
2677  
2678   /* Process incoming messages. */
2679
2680   /* JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT
2681      seconds we should just die.... */
2682
2683   start_time = time(NULL);
2684
2685   while(OPEN_FNUM(fnum) && fsp->granted_oplock)
2686   {
2687     if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False)
2688     {
2689       /*
2690        * Die if we got an error.
2691        */
2692
2693       if (smb_read_error == READ_EOF)
2694         DEBUG(0,("oplock_break: end of file from client\n"));
2695  
2696       if (smb_read_error == READ_ERROR)
2697         DEBUG(0,("oplock_break: receive_smb error (%s)\n",
2698                   strerror(errno)));
2699
2700       if (smb_read_error == READ_TIMEOUT)
2701         DEBUG(0,("oplock_break: receive_smb timed out after %d seconds.\n",
2702                   OPLOCK_BREAK_TIMEOUT));
2703
2704       DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \
2705 inode = %x).\n", fsp->name, fnum, dev, inode));
2706       shutdown_server = True;
2707       break;
2708     }
2709     process_smb(inbuf, outbuf);
2710
2711     /* We only need this in case a readraw crossed on the wire. */
2712     if(global_oplock_break)
2713       global_oplock_break = False;
2714
2715     /*
2716      * Die if we go over the time limit.
2717      */
2718
2719     if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT)
2720     {
2721       DEBUG(0,("oplock_break: no break received from client within \
2722 %d seconds.\n", OPLOCK_BREAK_TIMEOUT));
2723       DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \
2724 inode = %x).\n", fsp->name, fnum, dev, inode));
2725       shutdown_server = True;
2726       break;
2727     }
2728   }
2729
2730   /*
2731    * If the client did not respond we must die.
2732    */
2733
2734   if(shutdown_server)
2735   {
2736     DEBUG(0,("oplock_break: client failure in break - shutting down this smbd.\n"));
2737     close_sockets();
2738     close(oplock_sock);
2739     exit_server("oplock break failure");
2740   }
2741
2742   if(OPEN_FNUM(fnum))
2743   {
2744     /* The lockingX reply will have removed the oplock flag 
2745        from the sharemode. */
2746     /* Paranoia.... */
2747     fsp->granted_oplock = False;
2748   }
2749
2750   global_oplocks_open--;
2751
2752   /* Santity check - remove this later. JRA */
2753   if(global_oplocks_open < 0)
2754   {
2755     DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n",
2756               global_oplocks_open));
2757     abort();
2758   }
2759
2760   DEBUG(5,("oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \
2761 global_oplocks_open = %d\n", fnum, dev, inode, global_oplocks_open));
2762
2763   return True;
2764 }
2765
2766 /****************************************************************************
2767 Send an oplock break message to another smbd process. If the oplock is held 
2768 by the local smbd then call the oplock break function directly.
2769 ****************************************************************************/
2770
2771 BOOL request_oplock_break(min_share_mode_entry *share_entry, 
2772                           uint32 dev, uint32 inode)
2773 {
2774   char op_break_msg[OPLOCK_BREAK_MSG_LEN];
2775   struct sockaddr_in addr_out;
2776   int pid = getpid();
2777
2778   if(pid == share_entry->pid)
2779   {
2780     /* We are breaking our own oplock, make sure it's us. */
2781     if(share_entry->op_port != oplock_port)
2782     {
2783       DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \
2784 should be %d\n", pid, share_entry->op_port, oplock_port));
2785       return False;
2786     }
2787
2788     DEBUG(5,("request_oplock_break: breaking our own oplock\n"));
2789
2790     /* Call oplock break direct. */
2791     return oplock_break(dev, inode, &share_entry->time);
2792   }
2793
2794   /* We need to send a OPLOCK_BREAK_CMD message to the
2795      port in the share mode entry. */
2796
2797   SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD);
2798   SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid);
2799   SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev);
2800   SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode);
2801   SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec);
2802   SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec);
2803
2804   /* set the address and port */
2805   bzero((char *)&addr_out,sizeof(addr_out));
2806   addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2807   addr_out.sin_port = htons( share_entry->op_port );
2808   addr_out.sin_family = AF_INET;
2809    
2810   DEBUG(3,("request_oplock_break: sending a oplock break message to pid %d on port %d \
2811 for dev = %x, inode = %x\n", share_entry->pid, share_entry->op_port, dev, inode));
2812
2813   if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0,
2814          (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0)
2815   {
2816     DEBUG(0,("request_oplock_break: failed when sending a oplock break message \
2817 to pid %d on port %d for dev = %x, inode = %x. Error was %s\n",
2818          share_entry->pid, share_entry->op_port, dev, inode,
2819          strerror(errno)));
2820     return False;
2821   }
2822
2823   /*
2824    * Now we must await the oplock broken message coming back
2825    * from the target smbd process. Timeout if it fails to
2826    * return in OPLOCK_BREAK_TIMEOUT seconds.
2827    * While we get messages that aren't ours, loop.
2828    */
2829
2830   while(1)
2831   {
2832     char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN];
2833     int32 reply_msg_len;
2834     int16 reply_from_port;
2835     char *reply_msg_start;
2836
2837     if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply),
2838                              OPLOCK_BREAK_TIMEOUT * 1000) == False)
2839     {
2840       if(smb_read_error == READ_TIMEOUT)
2841         DEBUG(0,("request_oplock_break: no response received to oplock break request to \
2842 pid %d on port %d for dev = %x, inode = %x\n", share_entry->pid, 
2843                            share_entry->op_port, dev, inode));
2844       else
2845         DEBUG(0,("request_oplock_break: error in response received to oplock break request to \
2846 pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid, 
2847                          share_entry->op_port, dev, inode, strerror(errno)));
2848       return False;
2849     }
2850
2851     /* 
2852      * If the response we got was not an answer to our message, but
2853      * was a completely different request, push it onto the pending
2854      * udp message stack so that we can deal with it in the main loop.
2855      * It may be another oplock break request to us.
2856      */
2857
2858     /*
2859      * Local note from JRA. There exists the possibility of a denial
2860      * of service attack here by allowing non-root processes running
2861      * on a local machine sending many of these pending messages to
2862      * a smbd port. Currently I'm not sure how to restrict the messages
2863      * I will queue (although I could add a limit to the queue) to
2864      * those received by root processes only. There should be a 
2865      * way to make this bulletproof....
2866      */
2867
2868     reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET);
2869     reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET);
2870
2871     reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN];
2872
2873     if(reply_msg_len != OPLOCK_BREAK_MSG_LEN)
2874     {
2875       /* Ignore it. */
2876       DEBUG(0,("request_oplock_break: invalid message length received. Ignoring\n"));
2877       continue;
2878     }
2879
2880     if(((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) == 0) ||
2881        (reply_from_port != share_entry->op_port) ||
2882        (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], 
2883                &op_break_msg[OPLOCK_BREAK_PID_OFFSET],
2884                OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) != 0))
2885     {
2886       DEBUG(3,("request_oplock_break: received other message whilst awaiting \
2887 oplock break response from pid %d on port %d for dev = %x, inode = %x.\n",
2888              share_entry->pid, share_entry->op_port, dev, inode));
2889       if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False)
2890         return False;
2891       continue;
2892     }
2893
2894     break;
2895   }
2896
2897   DEBUG(3,("request_oplock_break: broke oplock.\n"));
2898
2899   return True;
2900 }
2901
2902 /****************************************************************************
2903 check if a snum is in use
2904 ****************************************************************************/
2905 BOOL snum_used(int snum)
2906 {
2907   int i;
2908   for (i=0;i<MAX_CONNECTIONS;i++)
2909     if (OPEN_CNUM(i) && (SNUM(i) == snum))
2910       return(True);
2911   return(False);
2912 }
2913
2914 /****************************************************************************
2915   reload the services file
2916   **************************************************************************/
2917 BOOL reload_services(BOOL test)
2918 {
2919   BOOL ret;
2920
2921   if (lp_loaded())
2922     {
2923       pstring fname;
2924       pstrcpy(fname,lp_configfile());
2925       if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
2926         {
2927           pstrcpy(servicesf,fname);
2928           test = False;
2929         }
2930     }
2931
2932   reopen_logs();
2933
2934   if (test && !lp_file_list_changed())
2935     return(True);
2936
2937   lp_killunused(snum_used);
2938
2939   ret = lp_load(servicesf,False);
2940
2941   /* perhaps the config filename is now set */
2942   if (!test)
2943     reload_services(True);
2944
2945   reopen_logs();
2946
2947   load_interfaces();
2948
2949   {
2950     extern int Client;
2951     if (Client != -1) {      
2952       set_socket_options(Client,"SO_KEEPALIVE");
2953       set_socket_options(Client,user_socket_options);
2954     }
2955   }
2956
2957   create_mangled_stack(lp_mangledstack());
2958
2959   /* this forces service parameters to be flushed */
2960   become_service(-1,True);
2961
2962   return(ret);
2963 }
2964
2965
2966
2967 /****************************************************************************
2968 this prevents zombie child processes
2969 ****************************************************************************/
2970 static int sig_hup()
2971 {
2972   BlockSignals(True,SIGHUP);
2973   DEBUG(0,("Got SIGHUP\n"));
2974   reload_services(False);
2975 #ifndef DONT_REINSTALL_SIG
2976   signal(SIGHUP,SIGNAL_CAST sig_hup);
2977 #endif
2978   BlockSignals(False,SIGHUP);
2979   return(0);
2980 }
2981
2982 /****************************************************************************
2983 Setup the groups a user belongs to.
2984 ****************************************************************************/
2985 int setup_groups(char *user, int uid, int gid, int *p_ngroups, 
2986                  int **p_igroups, gid_t **p_groups)
2987 {
2988   if (-1 == initgroups(user,gid))
2989     {
2990       if (getuid() == 0)
2991         {
2992           DEBUG(0,("Unable to initgroups!\n"));
2993           if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
2994             DEBUG(0,("This is probably a problem with the account %s\n",user));
2995         }
2996     }
2997   else
2998     {
2999       int i,ngroups;
3000       int *igroups;
3001       gid_t grp = 0;
3002       ngroups = getgroups(0,&grp);
3003       if (ngroups <= 0)
3004         ngroups = 32;
3005       igroups = (int *)malloc(sizeof(int)*ngroups);
3006       for (i=0;i<ngroups;i++)
3007         igroups[i] = 0x42424242;
3008       ngroups = getgroups(ngroups,(gid_t *)igroups);
3009
3010       if (igroups[0] == 0x42424242)
3011         ngroups = 0;
3012
3013       *p_ngroups = ngroups;
3014
3015       /* The following bit of code is very strange. It is due to the
3016          fact that some OSes use int* and some use gid_t* for
3017          getgroups, and some (like SunOS) use both, one in prototypes,
3018          and one in man pages and the actual code. Thus we detect it
3019          dynamically using some very ugly code */
3020       if (ngroups > 0)
3021         {
3022           /* does getgroups return ints or gid_t ?? */
3023           static BOOL groups_use_ints = True;
3024
3025           if (groups_use_ints && 
3026               ngroups == 1 && 
3027               SVAL(igroups,2) == 0x4242)
3028             groups_use_ints = False;
3029           
3030           for (i=0;groups_use_ints && i<ngroups;i++)
3031             if (igroups[i] == 0x42424242)
3032               groups_use_ints = False;
3033               
3034           if (groups_use_ints)
3035             {
3036               *p_igroups = igroups;
3037               *p_groups = (gid_t *)igroups;       
3038             }
3039           else
3040             {
3041               gid_t *groups = (gid_t *)igroups;
3042               igroups = (int *)malloc(sizeof(int)*ngroups);
3043               for (i=0;i<ngroups;i++)
3044                 igroups[i] = groups[i];
3045               *p_igroups = igroups;
3046               *p_groups = (gid_t *)groups;
3047             }
3048         }
3049       DEBUG(3,("%s is in %d groups\n",user,ngroups));
3050       for (i=0;i<ngroups;i++)
3051         DEBUG(3,("%d ",igroups[i]));
3052       DEBUG(3,("\n"));
3053     }
3054   return 0;
3055 }
3056
3057 /****************************************************************************
3058   make a connection to a service
3059 ****************************************************************************/
3060 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
3061 {
3062   int cnum;
3063   int snum;
3064   struct passwd *pass = NULL;
3065   connection_struct *pcon;
3066   BOOL guest = False;
3067   BOOL force = False;
3068   static BOOL first_connection = True;
3069
3070   strlower(service);
3071
3072   snum = find_service(service);
3073   if (snum < 0)
3074     {
3075       if (strequal(service,"IPC$"))
3076         {         
3077           DEBUG(3,("%s refusing IPC connection\n",timestring()));
3078           return(-3);
3079         }
3080
3081       DEBUG(0,("%s couldn't find service %s\n",timestring(),service));      
3082       return(-2);
3083     }
3084
3085   if (strequal(service,HOMES_NAME))
3086     {
3087       if (*user && Get_Pwnam(user,True))
3088         return(make_connection(user,user,password,pwlen,dev,vuid));
3089
3090       if (validated_username(vuid))
3091         {
3092           strcpy(user,validated_username(vuid));
3093           return(make_connection(user,user,password,pwlen,dev,vuid));
3094         }
3095     }
3096
3097   if (!lp_snum_ok(snum) || !check_access(snum)) {    
3098     return(-4);
3099   }
3100
3101   /* you can only connect to the IPC$ service as an ipc device */
3102   if (strequal(service,"IPC$"))
3103     strcpy(dev,"IPC");
3104
3105   if (*dev == '?' || !*dev)
3106     {
3107       if (lp_print_ok(snum))
3108         strcpy(dev,"LPT1:");
3109       else
3110         strcpy(dev,"A:");
3111     }
3112
3113   /* if the request is as a printer and you can't print then refuse */
3114   strupper(dev);
3115   if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
3116     DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
3117     return(-6);
3118   }
3119
3120   /* lowercase the user name */
3121   strlower(user);
3122
3123   /* add it as a possible user name */
3124   add_session_user(service);
3125
3126   /* shall we let them in? */
3127   if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
3128     {
3129       DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
3130       return(-1);
3131     }
3132   
3133   cnum = find_free_connection(str_checksum(service) + str_checksum(user));
3134   if (cnum < 0)
3135     {
3136       DEBUG(0,("%s couldn't find free connection\n",timestring()));      
3137       return(-1);
3138     }
3139
3140   pcon = &Connections[cnum];
3141   bzero((char *)pcon,sizeof(*pcon));
3142
3143   /* find out some info about the user */
3144   pass = Get_Pwnam(user,True);
3145
3146   if (pass == NULL)
3147     {
3148       DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); 
3149       return(-7);
3150     }
3151
3152   pcon->read_only = lp_readonly(snum);
3153
3154   {
3155     pstring list;
3156     StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
3157     string_sub(list,"%S",service);
3158
3159     if (user_in_list(user,list))
3160       pcon->read_only = True;
3161
3162     StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
3163     string_sub(list,"%S",service);
3164
3165     if (user_in_list(user,list))
3166       pcon->read_only = False;    
3167   }
3168
3169   /* admin user check */
3170
3171   /* JRA - original code denied admin user if the share was
3172      marked read_only. Changed as I don't think this is needed,
3173      but old code left in case there is a problem here.
3174    */
3175   if (user_in_list(user,lp_admin_users(snum)) 
3176 #if 0
3177       && !pcon->read_only)
3178 #else
3179       )
3180 #endif
3181     {
3182       pcon->admin_user = True;
3183       DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
3184     }
3185   else
3186     pcon->admin_user = False;
3187     
3188   pcon->force_user = force;
3189   pcon->vuid = vuid;
3190   pcon->uid = pass->pw_uid;
3191   pcon->gid = pass->pw_gid;
3192   pcon->num_files_open = 0;
3193   pcon->lastused = time(NULL);
3194   pcon->service = snum;
3195   pcon->used = True;
3196   pcon->printer = (strncmp(dev,"LPT",3) == 0);
3197   pcon->ipc = (strncmp(dev,"IPC",3) == 0);
3198   pcon->dirptr = NULL;
3199   pcon->veto_list = NULL;
3200   pcon->hide_list = NULL;
3201   string_set(&pcon->dirpath,"");
3202   string_set(&pcon->user,user);
3203
3204 #if HAVE_GETGRNAM 
3205   if (*lp_force_group(snum))
3206     {
3207       struct group *gptr;
3208       pstring gname;
3209
3210       StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
3211       /* default service may be a group name            */
3212       string_sub(gname,"%S",service);
3213       gptr = (struct group *)getgrnam(gname);
3214
3215       if (gptr)
3216         {
3217           pcon->gid = gptr->gr_gid;
3218           DEBUG(3,("Forced group %s\n",gname));
3219         }
3220       else
3221         DEBUG(1,("Couldn't find group %s\n",gname));
3222     }
3223 #endif
3224
3225   if (*lp_force_user(snum))
3226     {
3227       struct passwd *pass2;
3228       fstring fuser;
3229       fstrcpy(fuser,lp_force_user(snum));
3230       pass2 = (struct passwd *)Get_Pwnam(fuser,True);
3231       if (pass2)
3232         {
3233           pcon->uid = pass2->pw_uid;
3234           string_set(&pcon->user,fuser);
3235           fstrcpy(user,fuser);
3236           pcon->force_user = True;
3237           DEBUG(3,("Forced user %s\n",fuser));    
3238         }
3239       else
3240         DEBUG(1,("Couldn't find user %s\n",fuser));
3241     }
3242
3243   {
3244     pstring s;
3245     pstrcpy(s,lp_pathname(snum));
3246     standard_sub(cnum,s);
3247     string_set(&pcon->connectpath,s);
3248     DEBUG(3,("Connect path is %s\n",s));
3249   }
3250
3251   /* groups stuff added by ih */
3252   pcon->ngroups = 0;
3253   pcon->groups = NULL;
3254
3255   if (!IS_IPC(cnum))
3256     {
3257       /* Find all the groups this uid is in and store them. Used by become_user() */
3258       setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
3259       
3260       /* check number of connections */
3261       if (!claim_connection(cnum,
3262                             lp_servicename(SNUM(cnum)),
3263                             lp_max_connections(SNUM(cnum)),False))
3264         {
3265           DEBUG(1,("too many connections - rejected\n"));
3266           return(-8);
3267         }  
3268
3269       if (lp_status(SNUM(cnum)))
3270         claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
3271
3272       first_connection = False;
3273     } /* IS_IPC */
3274
3275   pcon->open = True;
3276
3277   /* execute any "root preexec = " line */
3278   if (*lp_rootpreexec(SNUM(cnum)))
3279     {
3280       pstring cmd;
3281       pstrcpy(cmd,lp_rootpreexec(SNUM(cnum)));
3282       standard_sub(cnum,cmd);
3283       DEBUG(5,("cmd=%s\n",cmd));
3284       smbrun(cmd,NULL,False);
3285     }
3286
3287   if (!become_user(cnum,pcon->vuid))
3288     {
3289       DEBUG(0,("Can't become connected user!\n"));
3290       pcon->open = False;
3291       if (!IS_IPC(cnum)) {
3292         yield_connection(cnum,
3293                          lp_servicename(SNUM(cnum)),
3294                          lp_max_connections(SNUM(cnum)));
3295         if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
3296       }
3297       return(-1);
3298     }
3299
3300   if (ChDir(pcon->connectpath) != 0)
3301     {
3302       DEBUG(0,("Can't change directory to %s (%s)\n",
3303                pcon->connectpath,strerror(errno)));
3304       pcon->open = False;
3305       unbecome_user();
3306       if (!IS_IPC(cnum)) {
3307         yield_connection(cnum,
3308                          lp_servicename(SNUM(cnum)),
3309                          lp_max_connections(SNUM(cnum)));
3310         if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
3311       }
3312       return(-5);      
3313     }
3314
3315   string_set(&pcon->origpath,pcon->connectpath);
3316
3317 #if SOFTLINK_OPTIMISATION
3318   /* resolve any soft links early */
3319   {
3320     pstring s;
3321     pstrcpy(s,pcon->connectpath);
3322     GetWd(s);
3323     string_set(&pcon->connectpath,s);
3324     ChDir(pcon->connectpath);
3325   }
3326 #endif
3327
3328   num_connections_open++;
3329   add_session_user(user);
3330   
3331   /* execute any "preexec = " line */
3332   if (*lp_preexec(SNUM(cnum)))
3333     {
3334       pstring cmd;
3335       pstrcpy(cmd,lp_preexec(SNUM(cnum)));
3336       standard_sub(cnum,cmd);
3337       smbrun(cmd,NULL,False);
3338     }
3339   
3340   /* we've finished with the sensitive stuff */
3341   unbecome_user();
3342
3343   /* Add veto/hide lists */
3344   if (!IS_IPC(cnum) && !IS_PRINT(cnum))
3345   {
3346     set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum)));
3347     set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum)));
3348   }
3349
3350   {
3351     DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
3352                             timestring(),
3353                             remote_machine,
3354                             client_addr(),
3355                             lp_servicename(SNUM(cnum)),user,
3356                             pcon->uid,
3357                             pcon->gid,
3358                             (int)getpid()));
3359   }
3360
3361   return(cnum);
3362 }
3363
3364
3365 /****************************************************************************
3366   find first available file slot
3367 ****************************************************************************/
3368 int find_free_file(void )
3369 {
3370   int i;
3371   /* we start at 1 here for an obscure reason I can't now remember,
3372      but I think is important :-) */
3373   for (i=1;i<MAX_OPEN_FILES;i++)
3374     if (!Files[i].open)
3375       return(i);
3376   DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
3377   return(-1);
3378 }
3379
3380 /****************************************************************************
3381   find first available connection slot, starting from a random position.
3382 The randomisation stops problems with the server dieing and clients
3383 thinking the server is still available.
3384 ****************************************************************************/
3385 static int find_free_connection(int hash )
3386 {
3387   int i;
3388   BOOL used=False;
3389   hash = (hash % (MAX_CONNECTIONS-2))+1;
3390
3391  again:
3392
3393   for (i=hash+1;i!=hash;)
3394     {
3395       if (!Connections[i].open && Connections[i].used == used) 
3396         {
3397           DEBUG(3,("found free connection number %d\n",i));
3398           return(i);
3399         }
3400       i++;
3401       if (i == MAX_CONNECTIONS)
3402         i = 1;
3403     }
3404
3405   if (!used)
3406     {
3407       used = !used;
3408       goto again;
3409     }
3410
3411   DEBUG(1,("ERROR! Out of connection structures\n"));
3412   return(-1);
3413 }
3414
3415
3416 /****************************************************************************
3417 reply for the core protocol
3418 ****************************************************************************/
3419 int reply_corep(char *outbuf)
3420 {
3421   int outsize = set_message(outbuf,1,0,True);
3422
3423   Protocol = PROTOCOL_CORE;
3424
3425   return outsize;
3426 }
3427
3428
3429 /****************************************************************************
3430 reply for the coreplus protocol
3431 ****************************************************************************/
3432 int reply_coreplus(char *outbuf)
3433 {
3434   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
3435   int outsize = set_message(outbuf,13,0,True);
3436   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
3437                                  readbraw and writebraw (possibly) */
3438   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
3439   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */  
3440
3441   Protocol = PROTOCOL_COREPLUS;
3442
3443   return outsize;
3444 }
3445
3446
3447 /****************************************************************************
3448 reply for the lanman 1.0 protocol
3449 ****************************************************************************/
3450 int reply_lanman1(char *outbuf)
3451 {
3452   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
3453   int secword=0;
3454   BOOL doencrypt = SMBENCRYPT();
3455   time_t t = time(NULL);
3456   /* We need to save and restore this as it can be destroyed
3457      if we call another server if security=server
3458      Thanks to Paul Nelson @ Thursby for pointing this out.
3459    */
3460   uint16 mid = SVAL(outbuf, smb_mid);
3461
3462   if (lp_security()>=SEC_USER) secword |= 1;
3463   if (doencrypt) secword |= 2;
3464
3465   set_message(outbuf,13,doencrypt?8:0,True);
3466   SSVAL(outbuf,smb_vwv1,secword); 
3467   /* Create a token value and add it to the outgoing packet. */
3468   if (doencrypt) 
3469     generate_next_challenge(smb_buf(outbuf));
3470
3471   Protocol = PROTOCOL_LANMAN1;
3472
3473   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
3474     DEBUG(3,("using password server validation\n"));
3475   if (doencrypt) set_challenge(smb_buf(outbuf));    
3476   }
3477
3478   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
3479   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
3480   SSVAL(outbuf,smb_vwv2,max_recv);
3481   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
3482   SSVAL(outbuf,smb_vwv4,1);
3483   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
3484                                  readbraw writebraw (possibly) */
3485   SIVAL(outbuf,smb_vwv6,getpid());
3486   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
3487
3488   put_dos_date(outbuf,smb_vwv8,t);
3489
3490   return (smb_len(outbuf)+4);
3491 }
3492
3493
3494 /****************************************************************************
3495 reply for the lanman 2.0 protocol
3496 ****************************************************************************/
3497 int reply_lanman2(char *outbuf)
3498 {
3499   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
3500   int secword=0;
3501   BOOL doencrypt = SMBENCRYPT();
3502   time_t t = time(NULL);
3503   /* We need to save and restore this as it can be destroyed
3504      if we call another server if security=server
3505      Thanks to Paul Nelson @ Thursby for pointing this out.
3506    */
3507   uint16 mid = SVAL(outbuf, smb_mid);
3508
3509   if (lp_security()>=SEC_USER) secword |= 1;
3510   if (doencrypt) secword |= 2;
3511
3512   set_message(outbuf,13,doencrypt?8:0,True);
3513   SSVAL(outbuf,smb_vwv1,secword); 
3514   /* Create a token value and add it to the outgoing packet. */
3515   if (doencrypt) 
3516     generate_next_challenge(smb_buf(outbuf));
3517
3518   SIVAL(outbuf,smb_vwv6,getpid());
3519
3520   Protocol = PROTOCOL_LANMAN2;
3521
3522   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
3523     DEBUG(3,("using password server validation\n"));
3524     if (doencrypt) set_challenge(smb_buf(outbuf));    
3525   }
3526
3527   CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
3528   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
3529   SSVAL(outbuf,smb_vwv2,max_recv);
3530   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
3531   SSVAL(outbuf,smb_vwv4,1);
3532   SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
3533   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
3534   put_dos_date(outbuf,smb_vwv8,t);
3535
3536   return (smb_len(outbuf)+4);
3537 }
3538
3539
3540 /****************************************************************************
3541 reply for the nt protocol
3542 ****************************************************************************/
3543 int reply_nt1(char *outbuf)
3544 {
3545   /* dual names + lock_and_read + nt SMBs + remote API calls */
3546   int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
3547 /*
3548   other valid capabilities which we may support at some time...
3549                      CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
3550                      CAP_LARGE_FILES|CAP_LARGE_READX|
3551                      CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
3552  */
3553
3554   int secword=0;
3555   BOOL doencrypt = SMBENCRYPT();
3556   time_t t = time(NULL);
3557   int data_len;
3558   int encrypt_len;
3559   char challenge_len = 8;
3560   /* We need to save and restore this as it can be destroyed
3561      if we call another server if security=server
3562      Thanks to Paul Nelson @ Thursby for pointing this out.
3563    */
3564   uint16 mid = SVAL(outbuf, smb_mid);
3565
3566   if (lp_readraw() && lp_writeraw())
3567   {
3568     capabilities |= CAP_RAW_MODE;
3569   }
3570
3571   if (lp_security()>=SEC_USER) secword |= 1;
3572   if (doencrypt) secword |= 2;
3573
3574   /* decide where (if) to put the encryption challenge, and
3575      follow it with the OEM'd domain name
3576    */
3577   encrypt_len = doencrypt?challenge_len:0;
3578 #if UNICODE
3579   data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
3580 #else
3581   data_len = encrypt_len + strlen(myworkgroup) + 1;
3582 #endif
3583
3584   set_message(outbuf,17,data_len,True);
3585
3586 #if UNICODE
3587   /* put the OEM'd domain name */
3588   PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
3589 #else
3590   strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
3591 #endif
3592
3593   CVAL(outbuf,smb_vwv1) = secword;
3594   /* Create a token value and add it to the outgoing packet. */
3595   if (doencrypt)
3596   {
3597     generate_next_challenge(smb_buf(outbuf));
3598
3599     /* Tell the nt machine how long the challenge is. */
3600     SSVALS(outbuf,smb_vwv16+1,challenge_len);
3601   }
3602
3603   Protocol = PROTOCOL_NT1;
3604
3605   if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
3606     DEBUG(3,("using password server validation\n"));
3607     if (doencrypt) set_challenge(smb_buf(outbuf));    
3608   }
3609
3610   SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
3611   SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
3612   SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
3613   SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
3614   SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
3615   SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
3616   SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
3617   put_long_date(outbuf+smb_vwv11+1,t);
3618   SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
3619   SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
3620
3621   return (smb_len(outbuf)+4);
3622 }
3623
3624 /* these are the protocol lists used for auto architecture detection:
3625
3626 WinNT 3.51:
3627 protocol [PC NETWORK PROGRAM 1.0]
3628 protocol [XENIX CORE]
3629 protocol [MICROSOFT NETWORKS 1.03]
3630 protocol [LANMAN1.0]
3631 protocol [Windows for Workgroups 3.1a]
3632 protocol [LM1.2X002]
3633 protocol [LANMAN2.1]
3634 protocol [NT LM 0.12]
3635
3636 Win95:
3637 protocol [PC NETWORK PROGRAM 1.0]
3638 protocol [XENIX CORE]
3639 protocol [MICROSOFT NETWORKS 1.03]
3640 protocol [LANMAN1.0]
3641 protocol [Windows for Workgroups 3.1a]
3642 protocol [LM1.2X002]
3643 protocol [LANMAN2.1]
3644 protocol [NT LM 0.12]
3645
3646 OS/2:
3647 protocol [PC NETWORK PROGRAM 1.0]
3648 protocol [XENIX CORE]
3649 protocol [LANMAN1.0]
3650 protocol [LM1.2X002]
3651 protocol [LANMAN2.1]
3652 */
3653
3654 /*
3655   * Modified to recognize the architecture of the remote machine better.
3656   *
3657   * This appears to be the matrix of which protocol is used by which
3658   * MS product.
3659        Protocol                       WfWg    Win95   WinNT  OS/2
3660        PC NETWORK PROGRAM 1.0          1       1       1      1
3661        XENIX CORE                                      2      2
3662        MICROSOFT NETWORKS 3.0          2       2       
3663        DOS LM1.2X002                   3       3       
3664        MICROSOFT NETWORKS 1.03                         3
3665        DOS LANMAN2.1                   4       4       
3666        LANMAN1.0                                       4      3
3667        Windows for Workgroups 3.1a     5       5       5
3668        LM1.2X002                                       6      4
3669        LANMAN2.1                                       7      5
3670        NT LM 0.12                              6       8
3671   *
3672   *  tim@fsg.com 09/29/95
3673   */
3674   
3675 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
3676 #define ARCH_WIN95    0x2
3677 #define ARCH_OS2      0xC      /* Again OS/2 is like NT */
3678 #define ARCH_WINNT    0x8
3679 #define ARCH_SAMBA    0x10
3680  
3681 #define ARCH_ALL      0x1F
3682  
3683 /* List of supported protocols, most desired first */
3684 struct {
3685   char *proto_name;
3686   char *short_name;
3687   int (*proto_reply_fn)(char *);
3688   int protocol_level;
3689 } supported_protocols[] = {
3690   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
3691   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
3692   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
3693   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
3694   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
3695   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
3696   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
3697   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
3698   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
3699   {NULL,NULL},
3700 };
3701
3702
3703 /****************************************************************************
3704   reply to a negprot
3705 ****************************************************************************/
3706 static int reply_negprot(char *inbuf,char *outbuf)
3707 {
3708   int outsize = set_message(outbuf,1,0,True);
3709   int Index=0;
3710   int choice= -1;
3711   int protocol;
3712   char *p;
3713   int bcc = SVAL(smb_buf(inbuf),-2);
3714   int arch = ARCH_ALL;
3715
3716   p = smb_buf(inbuf)+1;
3717   while (p < (smb_buf(inbuf) + bcc))
3718     { 
3719       Index++;
3720       DEBUG(3,("Requested protocol [%s]\n",p));
3721       if (strcsequal(p,"Windows for Workgroups 3.1a"))
3722         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
3723       else if (strcsequal(p,"DOS LM1.2X002"))
3724         arch &= ( ARCH_WFWG | ARCH_WIN95 );
3725       else if (strcsequal(p,"DOS LANMAN2.1"))
3726         arch &= ( ARCH_WFWG | ARCH_WIN95 );
3727       else if (strcsequal(p,"NT LM 0.12"))
3728         arch &= ( ARCH_WIN95 | ARCH_WINNT );
3729       else if (strcsequal(p,"LANMAN2.1"))
3730         arch &= ( ARCH_WINNT | ARCH_OS2 );
3731       else if (strcsequal(p,"LM1.2X002"))
3732         arch &= ( ARCH_WINNT | ARCH_OS2 );
3733       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
3734         arch &= ARCH_WINNT;
3735       else if (strcsequal(p,"XENIX CORE"))
3736         arch &= ( ARCH_WINNT | ARCH_OS2 );
3737       else if (strcsequal(p,"Samba")) {
3738         arch = ARCH_SAMBA;
3739         break;
3740       }
3741  
3742       p += strlen(p) + 2;
3743     }
3744     
3745   switch ( arch ) {
3746   case ARCH_SAMBA:
3747     set_remote_arch(RA_SAMBA);
3748     break;
3749   case ARCH_WFWG:
3750     set_remote_arch(RA_WFWG);
3751     break;
3752   case ARCH_WIN95:
3753     set_remote_arch(RA_WIN95);
3754     break;
3755   case ARCH_WINNT:
3756     set_remote_arch(RA_WINNT);
3757     break;
3758   case ARCH_OS2:
3759     set_remote_arch(RA_OS2);
3760     break;
3761   default:
3762     set_remote_arch(RA_UNKNOWN);
3763     break;
3764   }
3765  
3766   /* possibly reload - change of architecture */
3767   reload_services(True);      
3768     
3769   /* a special case to stop password server loops */
3770   if (Index == 1 && strequal(remote_machine,myhostname) && 
3771       lp_security()==SEC_SERVER)
3772     exit_server("Password server loop!");
3773   
3774   /* Check for protocols, most desirable first */
3775   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
3776     {
3777       p = smb_buf(inbuf)+1;
3778       Index = 0;
3779       if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
3780         while (p < (smb_buf(inbuf) + bcc))
3781           { 
3782             if (strequal(p,supported_protocols[protocol].proto_name))
3783               choice = Index;
3784             Index++;
3785             p += strlen(p) + 2;
3786           }
3787       if(choice != -1)
3788         break;
3789     }
3790   
3791   SSVAL(outbuf,smb_vwv0,choice);
3792   if(choice != -1) {
3793     extern fstring remote_proto;
3794     fstrcpy(remote_proto,supported_protocols[protocol].short_name);
3795     reload_services(True);          
3796     outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
3797     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
3798   }
3799   else {
3800     DEBUG(0,("No protocol supported !\n"));
3801   }
3802   SSVAL(outbuf,smb_vwv0,choice);
3803   
3804   DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3805
3806   return(outsize);
3807 }
3808
3809
3810 /****************************************************************************
3811 close all open files for a connection
3812 ****************************************************************************/
3813 static void close_open_files(int cnum)
3814 {
3815   int i;
3816   for (i=0;i<MAX_OPEN_FILES;i++)
3817     if( Files[i].cnum == cnum && Files[i].open) {
3818       close_file(i);
3819     }
3820 }
3821
3822
3823
3824 /****************************************************************************
3825 close a cnum
3826 ****************************************************************************/
3827 void close_cnum(int cnum, uint16 vuid)
3828 {
3829   DirCacheFlush(SNUM(cnum));
3830
3831   unbecome_user();
3832
3833   if (!OPEN_CNUM(cnum))
3834     {
3835       DEBUG(0,("Can't close cnum %d\n",cnum));
3836       return;
3837     }
3838
3839   DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3840                           timestring(),
3841                           remote_machine,client_addr(),
3842                           lp_servicename(SNUM(cnum))));
3843
3844   yield_connection(cnum,
3845                    lp_servicename(SNUM(cnum)),
3846                    lp_max_connections(SNUM(cnum)));
3847
3848   if (lp_status(SNUM(cnum)))
3849     yield_connection(cnum,"STATUS.",MAXSTATUS);
3850
3851   close_open_files(cnum);
3852   dptr_closecnum(cnum);
3853
3854   /* execute any "postexec = " line */
3855   if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
3856     {
3857       pstring cmd;
3858       strcpy(cmd,lp_postexec(SNUM(cnum)));
3859       standard_sub(cnum,cmd);
3860       smbrun(cmd,NULL,False);
3861       unbecome_user();
3862     }
3863
3864   unbecome_user();
3865   /* execute any "root postexec = " line */
3866   if (*lp_rootpostexec(SNUM(cnum)))
3867     {
3868       pstring cmd;
3869       strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3870       standard_sub(cnum,cmd);
3871       smbrun(cmd,NULL,False);
3872     }
3873
3874   Connections[cnum].open = False;
3875   num_connections_open--;
3876   if (Connections[cnum].ngroups && Connections[cnum].groups)
3877     {
3878       if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3879         free(Connections[cnum].groups);
3880       free(Connections[cnum].igroups);
3881       Connections[cnum].groups = NULL;
3882       Connections[cnum].igroups = NULL;
3883       Connections[cnum].ngroups = 0;
3884     }
3885
3886   free_namearray(Connections[cnum].veto_list);
3887   free_namearray(Connections[cnum].hide_list);
3888
3889   string_set(&Connections[cnum].user,"");
3890   string_set(&Connections[cnum].dirpath,"");
3891   string_set(&Connections[cnum].connectpath,"");
3892 }
3893
3894
3895 /****************************************************************************
3896 simple routines to do connection counting
3897 ****************************************************************************/
3898 BOOL yield_connection(int cnum,char *name,int max_connections)
3899 {
3900   struct connect_record crec;
3901   pstring fname;
3902   FILE *f;
3903   int mypid = getpid();
3904   int i;
3905
3906   DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3907
3908   if (max_connections <= 0)
3909     return(True);
3910
3911   bzero(&crec,sizeof(crec));
3912
3913   pstrcpy(fname,lp_lockdir());
3914   standard_sub(cnum,fname);
3915   trim_string(fname,"","/");
3916
3917   strcat(fname,"/");
3918   strcat(fname,name);
3919   strcat(fname,".LCK");
3920
3921   f = fopen(fname,"r+");
3922   if (!f)
3923     {
3924       DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
3925       return(False);
3926     }
3927
3928   fseek(f,0,SEEK_SET);
3929
3930   /* find a free spot */
3931   for (i=0;i<max_connections;i++)
3932     {
3933       if (fread(&crec,sizeof(crec),1,f) != 1)
3934         {
3935           DEBUG(2,("Entry not found in lock file %s\n",fname));
3936           fclose(f);
3937           return(False);
3938         }
3939       if (crec.pid == mypid && crec.cnum == cnum)
3940         break;
3941     }
3942
3943   if (crec.pid != mypid || crec.cnum != cnum)
3944     {
3945       fclose(f);
3946       DEBUG(2,("Entry not found in lock file %s\n",fname));
3947       return(False);
3948     }
3949
3950   bzero((void *)&crec,sizeof(crec));
3951   
3952   /* remove our mark */
3953   if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
3954       fwrite(&crec,sizeof(crec),1,f) != 1)
3955     {
3956       DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
3957       fclose(f);
3958       return(False);
3959     }
3960
3961   DEBUG(3,("Yield successful\n"));
3962
3963   fclose(f);
3964   return(True);
3965 }
3966
3967
3968 /****************************************************************************
3969 simple routines to do connection counting
3970 ****************************************************************************/
3971 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
3972 {
3973   struct connect_record crec;
3974   pstring fname;
3975   FILE *f;
3976   int snum = SNUM(cnum);
3977   int i,foundi= -1;
3978   int total_recs;
3979
3980   if (max_connections <= 0)
3981     return(True);
3982
3983   DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
3984
3985   pstrcpy(fname,lp_lockdir());
3986   standard_sub(cnum,fname);
3987   trim_string(fname,"","/");
3988
3989   if (!directory_exist(fname,NULL))
3990     mkdir(fname,0755);
3991
3992   strcat(fname,"/");
3993   strcat(fname,name);
3994   strcat(fname,".LCK");
3995
3996   if (!file_exist(fname,NULL))
3997     {
3998       int oldmask = umask(022);
3999       f = fopen(fname,"w");
4000       if (f) fclose(f);
4001       umask(oldmask);
4002     }
4003
4004   total_recs = file_size(fname) / sizeof(crec);
4005
4006   f = fopen(fname,"r+");
4007
4008   if (!f)
4009     {
4010       DEBUG(1,("couldn't open lock file %s\n",fname));
4011       return(False);
4012     }
4013
4014   /* find a free spot */
4015   for (i=0;i<max_connections;i++)
4016     {
4017
4018       if (i>=total_recs || 
4019           fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
4020           fread(&crec,sizeof(crec),1,f) != 1)
4021         {
4022           if (foundi < 0) foundi = i;
4023           break;
4024         }
4025
4026       if (Clear && crec.pid && !process_exists(crec.pid))
4027         {
4028           fseek(f,i*sizeof(crec),SEEK_SET);
4029           bzero((void *)&crec,sizeof(crec));
4030           fwrite(&crec,sizeof(crec),1,f);
4031           if (foundi < 0) foundi = i;
4032           continue;
4033         }
4034       if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
4035         {
4036           foundi=i;
4037           if (!Clear) break;
4038         }
4039     }  
4040
4041   if (foundi < 0)
4042     {
4043       DEBUG(3,("no free locks in %s\n",fname));
4044       fclose(f);
4045       return(False);
4046     }      
4047
4048   /* fill in the crec */
4049   bzero((void *)&crec,sizeof(crec));
4050   crec.magic = 0x280267;
4051   crec.pid = getpid();
4052   crec.cnum = cnum;
4053   crec.uid = Connections[cnum].uid;
4054   crec.gid = Connections[cnum].gid;
4055   StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
4056   crec.start = time(NULL);
4057
4058   StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
4059   StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
4060   
4061   /* make our mark */
4062   if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
4063       fwrite(&crec,sizeof(crec),1,f) != 1)
4064     {
4065       fclose(f);
4066       return(False);
4067     }
4068
4069   fclose(f);
4070   return(True);
4071 }
4072
4073 #if DUMP_CORE
4074 /*******************************************************************
4075 prepare to dump a core file - carefully!
4076 ********************************************************************/
4077 static BOOL dump_core(void)
4078 {
4079   char *p;
4080   pstring dname;
4081   pstrcpy(dname,debugf);
4082   if ((p=strrchr(dname,'/'))) *p=0;
4083   strcat(dname,"/corefiles");
4084   mkdir(dname,0700);
4085   sys_chown(dname,getuid(),getgid());
4086   chmod(dname,0700);
4087   if (chdir(dname)) return(False);
4088   umask(~(0700));
4089
4090 #ifndef NO_GETRLIMIT
4091 #ifdef RLIMIT_CORE
4092   {
4093     struct rlimit rlp;
4094     getrlimit(RLIMIT_CORE, &rlp);
4095     rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
4096     setrlimit(RLIMIT_CORE, &rlp);
4097     getrlimit(RLIMIT_CORE, &rlp);
4098     DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
4099   }
4100 #endif
4101 #endif
4102
4103
4104   DEBUG(0,("Dumping core in %s\n",dname));
4105   return(True);
4106 }
4107 #endif
4108
4109 /****************************************************************************
4110 exit the server
4111 ****************************************************************************/
4112 void exit_server(char *reason)
4113 {
4114   static int firsttime=1;
4115   int i;
4116
4117   if (!firsttime) exit(0);
4118   firsttime = 0;
4119
4120   unbecome_user();
4121   DEBUG(2,("Closing connections\n"));
4122   for (i=0;i<MAX_CONNECTIONS;i++)
4123     if (Connections[i].open)
4124       close_cnum(i,(uint16)-1);
4125 #ifdef DFS_AUTH
4126   if (dcelogin_atmost_once)
4127     dfs_unlogin();
4128 #endif
4129   if (!reason) {   
4130     int oldlevel = DEBUGLEVEL;
4131     DEBUGLEVEL = 10;
4132     DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
4133     if (last_inbuf)
4134       show_msg(last_inbuf);
4135     DEBUGLEVEL = oldlevel;
4136     DEBUG(0,("===============================================================\n"));
4137 #if DUMP_CORE
4138     if (dump_core()) return;
4139 #endif
4140   }    
4141
4142 #ifdef FAST_SHARE_MODES
4143   stop_share_mode_mgmt();
4144 #endif /* FAST_SHARE_MODES */
4145
4146   DEBUG(3,("%s Server exit  (%s)\n",timestring(),reason?reason:""));
4147   exit(0);
4148 }
4149
4150 /****************************************************************************
4151 do some standard substitutions in a string
4152 ****************************************************************************/
4153 void standard_sub(int cnum,char *str)
4154 {
4155   if (VALID_CNUM(cnum)) {
4156     char *p, *s, *home;
4157
4158     for ( s=str ; (p=strchr(s, '%')) != NULL ; s=p ) {
4159       switch (*(p+1)) {
4160         case 'H' : if ((home = get_home_dir(Connections[cnum].user))!=NULL)
4161                      string_sub(p,"%H",home);
4162                    else
4163                      p += 2;
4164                    break;
4165         case 'P' : string_sub(p,"%P",Connections[cnum].connectpath); break;
4166         case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break;
4167         case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break;
4168         case 'u' : string_sub(p,"%u",Connections[cnum].user); break;
4169         case '\0' : p++; break; /* don't run off the end of the string */
4170         default  : p+=2; break;
4171       }
4172     }
4173   }
4174   standard_sub_basic(str);
4175 }
4176
4177 /*
4178 These flags determine some of the permissions required to do an operation 
4179
4180 Note that I don't set NEED_WRITE on some write operations because they
4181 are used by some brain-dead clients when printing, and I don't want to
4182 force write permissions on print services.
4183 */
4184 #define AS_USER (1<<0)
4185 #define NEED_WRITE (1<<1)
4186 #define TIME_INIT (1<<2)
4187 #define CAN_IPC (1<<3)
4188 #define AS_GUEST (1<<5)
4189
4190
4191 /* 
4192    define a list of possible SMB messages and their corresponding
4193    functions. Any message that has a NULL function is unimplemented -
4194    please feel free to contribute implementations!
4195 */
4196 struct smb_message_struct
4197 {
4198   int code;
4199   char *name;
4200   int (*fn)();
4201   int flags;
4202 #if PROFILING
4203   unsigned long time;
4204 #endif
4205 }
4206  smb_messages[] = {
4207
4208     /* CORE PROTOCOL */
4209
4210    {SMBnegprot,"SMBnegprot",reply_negprot,0},
4211    {SMBtcon,"SMBtcon",reply_tcon,0},
4212    {SMBtdis,"SMBtdis",reply_tdis,0},
4213    {SMBexit,"SMBexit",reply_exit,0},
4214    {SMBioctl,"SMBioctl",reply_ioctl,0},
4215    {SMBecho,"SMBecho",reply_echo,0},
4216    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
4217    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
4218    {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
4219    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
4220    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
4221    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
4222    {SMBsearch,"SMBsearch",reply_search,AS_USER},
4223    {SMBopen,"SMBopen",reply_open,AS_USER},
4224
4225    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
4226    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
4227    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
4228
4229    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
4230    {SMBread,"SMBread",reply_read,AS_USER},
4231    {SMBwrite,"SMBwrite",reply_write,AS_USER},
4232    {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
4233    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
4234    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
4235    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
4236    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
4237
4238    /* this is a Pathworks specific call, allowing the 
4239       changing of the root path */
4240    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
4241
4242    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
4243    {SMBflush,"SMBflush",reply_flush,AS_USER},
4244    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
4245    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
4246    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
4247    {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
4248    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
4249    {SMBlock,"SMBlock",reply_lock,AS_USER},
4250    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
4251    
4252    /* CORE+ PROTOCOL FOLLOWS */
4253    
4254    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
4255    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
4256    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
4257    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
4258    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
4259    
4260    /* LANMAN1.0 PROTOCOL FOLLOWS */
4261    
4262    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
4263    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
4264    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
4265    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
4266    {SMBwritec,"SMBwritec",NULL,AS_USER},
4267    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
4268    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
4269    {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
4270    {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
4271    {SMBioctls,"SMBioctls",NULL,AS_USER},
4272    {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
4273    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
4274    
4275    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
4276    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
4277    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
4278    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
4279    
4280    {SMBffirst,"SMBffirst",reply_search,AS_USER},
4281    {SMBfunique,"SMBfunique",reply_search,AS_USER},
4282    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
4283
4284    /* LANMAN2.0 PROTOCOL FOLLOWS */
4285    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
4286    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
4287    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
4288    {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
4289
4290    /* messaging routines */
4291    {SMBsends,"SMBsends",reply_sends,AS_GUEST},
4292    {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
4293    {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
4294    {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
4295
4296    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
4297    
4298    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
4299    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
4300    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
4301    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
4302  };
4303
4304 /****************************************************************************
4305 return a string containing the function name of a SMB command
4306 ****************************************************************************/
4307 char *smb_fn_name(int type)
4308 {
4309   static char *unknown_name = "SMBunknown";
4310   static int num_smb_messages = 
4311     sizeof(smb_messages) / sizeof(struct smb_message_struct);
4312   int match;
4313
4314   for (match=0;match<num_smb_messages;match++)
4315     if (smb_messages[match].code == type)
4316       break;
4317
4318   if (match == num_smb_messages)
4319     return(unknown_name);
4320
4321   return(smb_messages[match].name);
4322 }
4323
4324
4325 /****************************************************************************
4326 do a switch on the message type, and return the response size
4327 ****************************************************************************/
4328 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
4329 {
4330   static int pid= -1;
4331   int outsize = 0;
4332   static int num_smb_messages = 
4333     sizeof(smb_messages) / sizeof(struct smb_message_struct);
4334   int match;
4335
4336 #if PROFILING
4337   struct timeval msg_start_time;
4338   struct timeval msg_end_time;
4339   static unsigned long total_time = 0;
4340
4341   GetTimeOfDay(&msg_start_time);
4342 #endif
4343
4344   if (pid == -1)
4345     pid = getpid();
4346
4347   errno = 0;
4348   last_message = type;
4349
4350   /* make sure this is an SMB packet */
4351   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
4352     {
4353       DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
4354       return(-1);
4355     }
4356
4357   for (match=0;match<num_smb_messages;match++)
4358     if (smb_messages[match].code == type)
4359       break;
4360
4361   if (match == num_smb_messages)
4362     {
4363       DEBUG(0,("Unknown message type %d!\n",type));
4364       outsize = reply_unknown(inbuf,outbuf);
4365     }
4366   else
4367     {
4368       DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
4369       if (smb_messages[match].fn)
4370         {
4371           int cnum = SVAL(inbuf,smb_tid);
4372           int flags = smb_messages[match].flags;
4373           uint16 session_tag = SVAL(inbuf,smb_uid);
4374
4375           /* does this protocol need to be run as root? */
4376           if (!(flags & AS_USER))
4377             unbecome_user();
4378
4379           /* does this protocol need to be run as the connected user? */
4380           if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
4381             if (flags & AS_GUEST) 
4382               flags &= ~AS_USER;
4383             else
4384               return(ERROR(ERRSRV,ERRinvnid));
4385           }
4386           /* this code is to work around a bug is MS client 3 without
4387              introducing a security hole - it needs to be able to do
4388              print queue checks as guest if it isn't logged in properly */
4389           if (flags & AS_USER)
4390             flags &= ~AS_GUEST;
4391
4392           /* does it need write permission? */
4393           if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
4394             return(ERROR(ERRSRV,ERRaccess));
4395
4396           /* ipc services are limited */
4397           if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
4398             return(ERROR(ERRSRV,ERRaccess));        
4399
4400           /* load service specific parameters */
4401           if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
4402             return(ERROR(ERRSRV,ERRaccess));
4403
4404           /* does this protocol need to be run as guest? */
4405           if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
4406             return(ERROR(ERRSRV,ERRaccess));
4407
4408           last_inbuf = inbuf;
4409
4410           outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
4411         }
4412       else
4413         {
4414           outsize = reply_unknown(inbuf,outbuf);
4415         }
4416     }
4417
4418 #if PROFILING
4419   GetTimeOfDay(&msg_end_time);
4420   if (!(smb_messages[match].flags & TIME_INIT))
4421     {
4422       smb_messages[match].time = 0;
4423       smb_messages[match].flags |= TIME_INIT;
4424     }
4425   {
4426     unsigned long this_time =     
4427       (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
4428         (msg_end_time.tv_usec - msg_start_time.tv_usec);
4429     smb_messages[match].time += this_time;
4430     total_time += this_time;
4431   }
4432   DEBUG(2,("TIME %s  %d usecs   %g pct\n",
4433            smb_fn_name(type),smb_messages[match].time,
4434         (100.0*smb_messages[match].time) / total_time));
4435 #endif
4436
4437   return(outsize);
4438 }
4439
4440
4441 /****************************************************************************
4442   construct a chained reply and add it to the already made reply
4443   **************************************************************************/
4444 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
4445 {
4446   static char *orig_inbuf;
4447   static char *orig_outbuf;
4448   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
4449   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
4450   char *inbuf2, *outbuf2;
4451   int outsize2;
4452   char inbuf_saved[smb_wct];
4453   char outbuf_saved[smb_wct];
4454   extern int chain_size;
4455   int wct = CVAL(outbuf,smb_wct);
4456   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
4457
4458   /* maybe its not chained */
4459   if (smb_com2 == 0xFF) {
4460     CVAL(outbuf,smb_vwv0) = 0xFF;
4461     return outsize;
4462   }
4463
4464   if (chain_size == 0) {
4465     /* this is the first part of the chain */
4466     orig_inbuf = inbuf;
4467     orig_outbuf = outbuf;
4468   }
4469
4470   /* we need to tell the client where the next part of the reply will be */
4471   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
4472   CVAL(outbuf,smb_vwv0) = smb_com2;
4473
4474   /* remember how much the caller added to the chain, only counting stuff
4475      after the parameter words */
4476   chain_size += outsize - smb_wct;
4477
4478   /* work out pointers into the original packets. The
4479      headers on these need to be filled in */
4480   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
4481   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
4482
4483   /* remember the original command type */
4484   smb_com1 = CVAL(orig_inbuf,smb_com);
4485
4486   /* save the data which will be overwritten by the new headers */
4487   memcpy(inbuf_saved,inbuf2,smb_wct);
4488   memcpy(outbuf_saved,outbuf2,smb_wct);
4489
4490   /* give the new packet the same header as the last part of the SMB */
4491   memmove(inbuf2,inbuf,smb_wct);
4492
4493   /* create the in buffer */
4494   CVAL(inbuf2,smb_com) = smb_com2;
4495
4496   /* create the out buffer */
4497   bzero(outbuf2,smb_size);
4498   set_message(outbuf2,0,0,True);
4499   CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
4500   
4501   memcpy(outbuf2+4,inbuf2+4,4);
4502   CVAL(outbuf2,smb_rcls) = SUCCESS;
4503   CVAL(outbuf2,smb_reh) = 0;
4504   CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set 
4505                                                                   means a reply */
4506   SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
4507   SSVAL(outbuf2,smb_err,SUCCESS);
4508   SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
4509   SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
4510   SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
4511   SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
4512
4513   DEBUG(3,("Chained message\n"));
4514   show_msg(inbuf2);
4515
4516   /* process the request */
4517   outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
4518                             bufsize-chain_size);
4519
4520   /* copy the new reply and request headers over the old ones, but
4521      preserve the smb_com field */
4522   memmove(orig_outbuf,outbuf2,smb_wct);
4523   CVAL(orig_outbuf,smb_com) = smb_com1;
4524
4525   /* restore the saved data, being careful not to overwrite any
4526    data from the reply header */
4527   memcpy(inbuf2,inbuf_saved,smb_wct);
4528   {
4529     int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
4530     if (ofs < 0) ofs = 0;
4531     memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
4532   }
4533
4534   return outsize2;
4535 }
4536
4537
4538
4539 /****************************************************************************
4540   construct a reply to the incoming packet
4541 ****************************************************************************/
4542 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
4543 {
4544   int type = CVAL(inbuf,smb_com);
4545   int outsize = 0;
4546   int msg_type = CVAL(inbuf,0);
4547   extern int chain_size;
4548
4549   smb_last_time = time(NULL);
4550
4551   chain_size = 0;
4552   chain_fnum = -1;
4553
4554   bzero(outbuf,smb_size);
4555
4556   if (msg_type != 0)
4557     return(reply_special(inbuf,outbuf));  
4558
4559   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
4560   set_message(outbuf,0,0,True);
4561   
4562   memcpy(outbuf+4,inbuf+4,4);
4563   CVAL(outbuf,smb_rcls) = SUCCESS;
4564   CVAL(outbuf,smb_reh) = 0;
4565   CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set 
4566                                                              means a reply */
4567   SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
4568   SSVAL(outbuf,smb_err,SUCCESS);
4569   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
4570   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
4571   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
4572   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
4573
4574   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
4575
4576   outsize += chain_size;
4577
4578   if(outsize > 4)
4579     smb_setlen(outbuf,outsize - 4);
4580   return(outsize);
4581 }
4582
4583 /****************************************************************************
4584   process commands from the client
4585 ****************************************************************************/
4586 static void process(void)
4587 {
4588   extern int Client;
4589
4590   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4591   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4592   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
4593     return;
4594
4595   InBuffer += SMB_ALIGNMENT;
4596   OutBuffer += SMB_ALIGNMENT;
4597
4598 #if PRIME_NMBD
4599   DEBUG(3,("priming nmbd\n"));
4600   {
4601     struct in_addr ip;
4602     ip = *interpret_addr2("localhost");
4603     if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
4604     *OutBuffer = 0;
4605     send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
4606   }
4607 #endif    
4608
4609   while (True)
4610   {
4611     int deadtime = lp_deadtime()*60;
4612     int counter;
4613     int last_keepalive=0;
4614     int service_load_counter = 0;
4615     BOOL got_smb = False;
4616
4617     if (deadtime <= 0)
4618       deadtime = DEFAULT_SMBD_TIMEOUT;
4619
4620     if (lp_readprediction())
4621       do_read_prediction();
4622
4623     errno = 0;      
4624
4625     for (counter=SMBD_SELECT_LOOP; 
4626           !receive_message_or_smb(Client,oplock_sock,
4627                       InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb); 
4628           counter += SMBD_SELECT_LOOP)
4629     {
4630       int i;
4631       time_t t;
4632       BOOL allidle = True;
4633       extern int keepalive;
4634
4635       if (counter > 365 * 3600) /* big number of seconds. */
4636       {
4637         counter = 0;
4638         service_load_counter = 0;
4639       }
4640
4641       if (smb_read_error == READ_EOF) 
4642       {
4643         DEBUG(3,("end of file from client\n"));
4644         return;
4645       }
4646
4647       if (smb_read_error == READ_ERROR) 
4648       {
4649         DEBUG(3,("receive_smb error (%s) exiting\n",
4650                   strerror(errno)));
4651         return;
4652       }
4653
4654       t = time(NULL);
4655
4656       /* become root again if waiting */
4657       unbecome_user();
4658
4659       /* check for smb.conf reload */
4660       if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
4661       {
4662         service_load_counter = counter;
4663
4664         /* reload services, if files have changed. */
4665         reload_services(True);
4666       }
4667
4668       /* automatic timeout if all connections are closed */      
4669       if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) 
4670       {
4671         DEBUG(2,("%s Closing idle connection\n",timestring()));
4672         return;
4673       }
4674
4675       if (keepalive && (counter-last_keepalive)>keepalive) 
4676       {
4677         extern int password_client;
4678         if (!send_keepalive(Client))
4679         { 
4680           DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
4681           return;
4682         }           
4683         /* also send a keepalive to the password server if its still
4684            connected */
4685         if (password_client != -1)
4686           send_keepalive(password_client);
4687         last_keepalive = counter;
4688       }
4689
4690       /* check for connection timeouts */
4691       for (i=0;i<MAX_CONNECTIONS;i++)
4692         if (Connections[i].open)
4693         {
4694           /* close dirptrs on connections that are idle */
4695           if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
4696             dptr_idlecnum(i);
4697
4698           if (Connections[i].num_files_open > 0 ||
4699                      (t-Connections[i].lastused)<deadtime)
4700             allidle = False;
4701         }
4702
4703       if (allidle && num_connections_open>0) 
4704       {
4705         DEBUG(2,("%s Closing idle connection 2\n",timestring()));
4706         return;
4707       }
4708     }
4709
4710     if(got_smb)
4711       process_smb(InBuffer, OutBuffer);
4712     else
4713       process_local_message(oplock_sock, InBuffer, BUFFER_SIZE);
4714   }
4715 }
4716
4717
4718 /****************************************************************************
4719   initialise connect, service and file structs
4720 ****************************************************************************/
4721 static void init_structs(void )
4722 {
4723   int i;
4724   get_myname(myhostname,NULL);
4725
4726   for (i=0;i<MAX_CONNECTIONS;i++)
4727     {
4728       Connections[i].open = False;
4729       Connections[i].num_files_open=0;
4730       Connections[i].lastused=0;
4731       Connections[i].used=False;
4732       string_init(&Connections[i].user,"");
4733       string_init(&Connections[i].dirpath,"");
4734       string_init(&Connections[i].connectpath,"");
4735       string_init(&Connections[i].origpath,"");
4736     }
4737
4738   for (i=0;i<MAX_OPEN_FILES;i++)
4739     {
4740       Files[i].open = False;
4741       string_init(&Files[i].name,"");
4742
4743     }
4744
4745   for (i=0;i<MAX_OPEN_FILES;i++)
4746     {
4747       file_fd_struct *fd_ptr = &FileFd[i];
4748       fd_ptr->ref_count = 0;
4749       fd_ptr->dev = (int32)-1;
4750       fd_ptr->inode = (int32)-1;
4751       fd_ptr->fd = -1;
4752       fd_ptr->fd_readonly = -1;
4753       fd_ptr->fd_writeonly = -1;
4754       fd_ptr->real_open_flags = -1;
4755     }
4756
4757   init_dptrs();
4758 }
4759
4760 /****************************************************************************
4761 usage on the program
4762 ****************************************************************************/
4763 static void usage(char *pname)
4764 {
4765   DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4766
4767   printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
4768   printf("Version %s\n",VERSION);
4769   printf("\t-D                    become a daemon\n");
4770   printf("\t-p port               listen on the specified port\n");
4771   printf("\t-d debuglevel         set the debuglevel\n");
4772   printf("\t-l log basename.      Basename for log/debug files\n");
4773   printf("\t-s services file.     Filename of services file\n");
4774   printf("\t-P                    passive only\n");
4775   printf("\t-a                    overwrite log file, don't append\n");
4776   printf("\n");
4777 }
4778
4779
4780 /****************************************************************************
4781   main program
4782 ****************************************************************************/
4783  int main(int argc,char *argv[])
4784 {
4785   extern BOOL append_log;
4786   /* shall I run as a daemon */
4787   BOOL is_daemon = False;
4788   int port = SMB_PORT;
4789   int opt;
4790   extern char *optarg;
4791   char pidFile[100] = { 0 };
4792
4793 #ifdef NEED_AUTH_PARAMETERS
4794   set_auth_parameters(argc,argv);
4795 #endif
4796
4797 #ifdef SecureWare
4798   setluid(0);
4799 #endif
4800
4801   append_log = True;
4802
4803   TimeInit();
4804
4805   strcpy(debugf,SMBLOGFILE);  
4806
4807   setup_logging(argv[0],False);
4808
4809   charset_initialise();
4810
4811   /* make absolutely sure we run as root - to handle cases whre people
4812      are crazy enough to have it setuid */
4813 #ifdef USE_SETRES
4814   setresuid(0,0,0);
4815 #else
4816   setuid(0);
4817   seteuid(0);
4818   setuid(0);
4819   seteuid(0);
4820 #endif
4821
4822   fault_setup(exit_server);
4823   signal(SIGTERM , SIGNAL_CAST dflt_sig);
4824
4825   /* we want total control over the permissions on created files,
4826      so set our umask to 0 */
4827   umask(0);
4828
4829   GetWd(OriginalDir);
4830
4831   init_uid();
4832
4833   /* this is for people who can't start the program correctly */
4834   while (argc > 1 && (*argv[1] != '-'))
4835     {
4836       argv++;
4837       argc--;
4838     }
4839
4840   while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
4841     switch (opt)
4842       {
4843       case 'f':
4844         strncpy(pidFile, optarg, sizeof(pidFile));
4845         break;
4846       case 'O':
4847         strcpy(user_socket_options,optarg);
4848         break;
4849       case 'i':
4850         strcpy(scope,optarg);
4851         break;
4852       case 'P':
4853         {
4854           extern BOOL passive;
4855           passive = True;
4856         }
4857         break;  
4858       case 's':
4859         strcpy(servicesf,optarg);
4860         break;
4861       case 'l':
4862         strcpy(debugf,optarg);
4863         break;
4864       case 'a':
4865         {
4866           extern BOOL append_log;
4867           append_log = !append_log;
4868         }
4869         break;
4870       case 'D':
4871         is_daemon = True;
4872         break;
4873       case 'd':
4874         if (*optarg == 'A')
4875           DEBUGLEVEL = 10000;
4876         else
4877           DEBUGLEVEL = atoi(optarg);
4878         break;
4879       case 'p':
4880         port = atoi(optarg);
4881         break;
4882       case 'h':
4883         usage(argv[0]);
4884         exit(0);
4885         break;
4886       default:
4887         usage(argv[0]);
4888         exit(1);
4889       }
4890
4891   reopen_logs();
4892
4893   DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4894   DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n"));
4895
4896 #ifndef NO_GETRLIMIT
4897 #ifdef RLIMIT_NOFILE
4898   {
4899     struct rlimit rlp;
4900     getrlimit(RLIMIT_NOFILE, &rlp);
4901     rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4902     setrlimit(RLIMIT_NOFILE, &rlp);
4903     getrlimit(RLIMIT_NOFILE, &rlp);
4904     DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4905   }
4906 #endif
4907 #endif
4908
4909   
4910   DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4911         getuid(),getgid(),geteuid(),getegid()));
4912
4913   if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
4914     {
4915       DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
4916       exit(1);
4917     }
4918
4919   init_structs();
4920
4921   if (!reload_services(False))
4922     return(-1); 
4923
4924   codepage_initialise(lp_client_code_page());
4925
4926   strcpy(myworkgroup, lp_workgroup());
4927
4928 #ifndef NO_SIGNAL_TEST
4929   signal(SIGHUP,SIGNAL_CAST sig_hup);
4930 #endif
4931   
4932   DEBUG(3,("%s loaded services\n",timestring()));
4933
4934   if (!is_daemon && !is_a_socket(0))
4935     {
4936       DEBUG(0,("standard input is not a socket, assuming -D option\n"));
4937       is_daemon = True;
4938     }
4939
4940   if (is_daemon)
4941     {
4942       DEBUG(3,("%s becoming a daemon\n",timestring()));
4943       become_daemon();
4944     }
4945
4946   if (*pidFile)
4947     {
4948       int     fd;
4949       char    buf[20];
4950
4951       if ((fd = open(pidFile,
4952 #ifdef O_NONBLOCK
4953          O_NONBLOCK | 
4954 #endif
4955          O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
4956         {
4957            DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
4958            exit(1);
4959         }
4960       if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
4961         {
4962           DEBUG(0,("ERROR: smbd is already running\n"));
4963           exit(1);
4964         }
4965       sprintf(buf, "%u\n", (unsigned int) getpid());
4966       if (write(fd, buf, strlen(buf)) < 0)
4967         {
4968           DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
4969           exit(1);
4970         }
4971       /* Leave pid file open & locked for the duration... */
4972     }
4973
4974   if (!open_sockets(is_daemon,port))
4975     exit(1);
4976
4977 #ifdef FAST_SHARE_MODES
4978   if (!start_share_mode_mgmt())
4979     exit(1);
4980 #endif /* FAST_SHARE_MODES */
4981
4982   /* possibly reload the services file. */
4983   reload_services(True);
4984
4985   max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
4986
4987   if (*lp_rootdir())
4988     {
4989       if (sys_chroot(lp_rootdir()) == 0)
4990         DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
4991     }
4992
4993   /* Setup the oplock IPC socket. */
4994   if(!open_oplock_ipc())
4995     exit(1);
4996
4997   process();
4998   close_sockets();
4999
5000   exit_server("normal exit");
5001   return(0);
5002 }
5003
5004