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