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