rewrote the password server code using the new clientgen.c client
[Samba.git] / source / smbd / server.c
blobf6a43a536da336236e4c4de3d738eadd38200814
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB server routines
5 Copyright (C) Andrew Tridgell 1992-1997
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.
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.
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.
22 #include "includes.h"
23 #include "trans2.h"
25 pstring servicesf = CONFIGFILE;
26 extern pstring debugf;
27 extern pstring sesssetup_user;
28 extern fstring myworkgroup;
30 char *InBuffer = NULL;
31 char *OutBuffer = NULL;
32 char *last_inbuf = NULL;
34 int am_parent = 1;
35 int atexit_set = 0;
37 /* the last message the was processed */
38 int last_message = -1;
40 /* a useful macro to debug the last message processed */
41 #define LAST_MESSAGE() smb_fn_name(last_message)
43 extern pstring scope;
44 extern int DEBUGLEVEL;
45 extern int case_default;
46 extern BOOL case_sensitive;
47 extern BOOL case_preserve;
48 extern BOOL use_mangled_map;
49 extern BOOL short_case_preserve;
50 extern BOOL case_mangle;
51 extern time_t smb_last_time;
53 extern int smb_read_error;
55 extern pstring user_socket_options;
57 connection_struct Connections[MAX_CONNECTIONS];
58 files_struct Files[MAX_OPEN_FILES];
61 * Indirection for file fd's. Needed as POSIX locking
62 * is based on file/process, not fd/process.
64 file_fd_struct FileFd[MAX_OPEN_FILES];
65 int max_file_fd_used = 0;
67 extern int Protocol;
69 /*
70 * Size of data we can send to client. Set
71 * by the client for all protocols above CORE.
72 * Set by us for CORE protocol.
74 int max_send = BUFFER_SIZE;
76 * Size of the data we can receive. Set by us.
77 * Can be modified by the max xmit parameter.
79 int max_recv = BUFFER_SIZE;
81 /* a fnum to use when chaining */
82 int chain_fnum = -1;
84 /* number of open connections */
85 static int num_connections_open = 0;
87 /* Oplock ipc UDP socket. */
88 int oplock_sock = -1;
89 uint16 oplock_port = 0;
90 /* Current number of oplocks we have outstanding. */
91 int32 global_oplocks_open = 0;
93 BOOL global_oplock_break = False;
95 extern fstring remote_machine;
97 pstring OriginalDir;
99 /* these can be set by some functions to override the error codes */
100 int unix_ERR_class=SUCCESS;
101 int unix_ERR_code=0;
104 extern int extra_time_offset;
106 extern pstring myhostname;
108 static int find_free_connection(int hash);
110 /* for readability... */
111 #define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
112 #define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
113 #define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
114 #define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
115 #define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
117 /****************************************************************************
118 when exiting, take the whole family
119 ****************************************************************************/
120 void *dflt_sig(void)
122 exit_server("caught signal");
123 return 0; /* Keep -Wall happy :-) */
125 /****************************************************************************
126 Send a SIGTERM to our process group.
127 *****************************************************************************/
128 void killkids(void)
130 if(am_parent) kill(0,SIGTERM);
133 /****************************************************************************
134 change a dos mode to a unix mode
135 base permission for files:
136 everybody gets read bit set
137 dos readonly is represented in unix by removing everyone's write bit
138 dos archive is represented in unix by the user's execute bit
139 dos system is represented in unix by the group's execute bit
140 dos hidden is represented in unix by the other's execute bit
141 Then apply create mask,
142 then add force bits.
143 base permission for directories:
144 dos directory is represented in unix by unix's dir bit and the exec bit
145 Then apply create mask,
146 then add force bits.
147 ****************************************************************************/
148 mode_t unix_mode(int cnum,int dosmode)
150 mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
152 if ( !IS_DOS_READONLY(dosmode) )
153 result |= (S_IWUSR | S_IWGRP | S_IWOTH);
155 if (IS_DOS_DIR(dosmode)) {
156 /* We never make directories read only for the owner as under DOS a user
157 can always create a file in a read-only directory. */
158 result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
159 /* Apply directory mask */
160 result &= lp_dir_mode(SNUM(cnum));
161 /* Add in force bits */
162 result |= lp_force_dir_mode(SNUM(cnum));
163 } else {
164 if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
165 result |= S_IXUSR;
167 if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
168 result |= S_IXGRP;
170 if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
171 result |= S_IXOTH;
173 /* Apply mode mask */
174 result &= lp_create_mode(SNUM(cnum));
175 /* Add in force bits */
176 result |= lp_force_create_mode(SNUM(cnum));
178 return(result);
182 /****************************************************************************
183 change a unix mode to a dos mode
184 ****************************************************************************/
185 int dos_mode(int cnum,char *path,struct stat *sbuf)
187 int result = 0;
188 extern struct current_user current_user;
190 DEBUG(8,("dos_mode: %d %s\n", cnum, path));
192 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
193 if (!((sbuf->st_mode & S_IWOTH) ||
194 Connections[cnum].admin_user ||
195 ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) ||
196 ((sbuf->st_mode & S_IWGRP) &&
197 in_group(sbuf->st_gid,current_user.gid,
198 current_user.ngroups,current_user.igroups))))
199 result |= aRONLY;
200 } else {
201 if ((sbuf->st_mode & S_IWUSR) == 0)
202 result |= aRONLY;
205 if (MAP_ARCHIVE(cnum) && ((sbuf->st_mode & S_IXUSR) != 0))
206 result |= aARCH;
208 if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
209 result |= aSYSTEM;
211 if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
212 result |= aHIDDEN;
214 if (S_ISDIR(sbuf->st_mode))
215 result = aDIR | (result & aRONLY);
217 #ifdef S_ISLNK
218 #if LINKS_READ_ONLY
219 if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
220 result |= aRONLY;
221 #endif
222 #endif
224 /* hide files with a name starting with a . */
225 if (lp_hide_dot_files(SNUM(cnum)))
227 char *p = strrchr(path,'/');
228 if (p)
229 p++;
230 else
231 p = path;
233 if (p[0] == '.' && p[1] != '.' && p[1] != 0)
234 result |= aHIDDEN;
237 /* Optimization : Only call is_hidden_path if it's not already
238 hidden. */
239 if (!(result & aHIDDEN) && IS_HIDDEN_PATH(cnum,path))
241 result |= aHIDDEN;
244 DEBUG(8,("dos_mode returning "));
246 if (result & aHIDDEN) DEBUG(8, ("h"));
247 if (result & aRONLY ) DEBUG(8, ("r"));
248 if (result & aSYSTEM) DEBUG(8, ("s"));
249 if (result & aDIR ) DEBUG(8, ("d"));
250 if (result & aARCH ) DEBUG(8, ("a"));
252 DEBUG(8,("\n"));
254 return(result);
257 /*******************************************************************
258 chmod a file - but preserve some bits
259 ********************************************************************/
260 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st)
262 struct stat st1;
263 int mask=0;
264 int tmp;
265 int unixmode;
267 if (!st) {
268 st = &st1;
269 if (sys_stat(fname,st)) return(-1);
272 if (S_ISDIR(st->st_mode)) dosmode |= aDIR;
274 if (dos_mode(cnum,fname,st) == dosmode) return(0);
276 unixmode = unix_mode(cnum,dosmode);
278 /* preserve the s bits */
279 mask |= (S_ISUID | S_ISGID);
281 /* preserve the t bit */
282 #ifdef S_ISVTX
283 mask |= S_ISVTX;
284 #endif
286 /* possibly preserve the x bits */
287 if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR;
288 if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP;
289 if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH;
291 unixmode |= (st->st_mode & mask);
293 /* if we previously had any r bits set then leave them alone */
294 if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
295 unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
296 unixmode |= tmp;
299 /* if we previously had any w bits set then leave them alone
300 if the new mode is not rdonly */
301 if (!IS_DOS_READONLY(dosmode) &&
302 (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) {
303 unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
304 unixmode |= tmp;
307 return(sys_chmod(fname,unixmode));
310 /*******************************************************************
311 Wrapper around sys_utime that possibly allows DOS semantics rather
312 than POSIX.
313 *******************************************************************/
315 int file_utime(int cnum, char *fname, struct utimbuf *times)
317 extern struct current_user current_user;
318 struct stat sb;
319 int ret = -1;
321 if(sys_utime(fname, times) == 0)
322 return 0;
324 if((errno != EPERM) || !lp_dos_filetimes(SNUM(cnum)))
325 return -1;
327 /* We have permission (given by the Samba admin) to
328 break POSIX semantics and allow a user to change
329 the time on a file they don't own but can write to
330 (as DOS does).
333 if(sys_stat(fname,&sb) != 0)
334 return -1;
336 /* Check if we have write access. */
337 if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum)))
339 if (((sb.st_mode & S_IWOTH) ||
340 Connections[cnum].admin_user ||
341 ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) ||
342 ((sb.st_mode & S_IWGRP) &&
343 in_group(sb.st_gid,current_user.gid,
344 current_user.ngroups,current_user.igroups))))
346 /* We are allowed to become root and change the filetime. */
347 become_root(False);
348 ret = sys_utime(fname, times);
349 unbecome_root(False);
353 return ret;
356 /*******************************************************************
357 Change a filetime - possibly allowing DOS semantics.
358 *******************************************************************/
360 BOOL set_filetime(int cnum, char *fname, time_t mtime)
362 struct utimbuf times;
364 if (null_mtime(mtime)) return(True);
366 times.modtime = times.actime = mtime;
368 if (file_utime(cnum, fname, &times)) {
369 DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
372 return(True);
375 /****************************************************************************
376 check if two filenames are equal
378 this needs to be careful about whether we are case sensitive
379 ****************************************************************************/
380 static BOOL fname_equal(char *name1, char *name2)
382 int l1 = strlen(name1);
383 int l2 = strlen(name2);
385 /* handle filenames ending in a single dot */
386 if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot())
388 BOOL ret;
389 name1[l1-1] = 0;
390 ret = fname_equal(name1,name2);
391 name1[l1-1] = '.';
392 return(ret);
395 if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot())
397 BOOL ret;
398 name2[l2-1] = 0;
399 ret = fname_equal(name1,name2);
400 name2[l2-1] = '.';
401 return(ret);
404 /* now normal filename handling */
405 if (case_sensitive)
406 return(strcmp(name1,name2) == 0);
408 return(strequal(name1,name2));
412 /****************************************************************************
413 mangle the 2nd name and check if it is then equal to the first name
414 ****************************************************************************/
415 static BOOL mangled_equal(char *name1, char *name2)
417 pstring tmpname;
419 if (is_8_3(name2, True))
420 return(False);
422 strcpy(tmpname,name2);
423 mangle_name_83(tmpname);
425 return(strequal(name1,tmpname));
429 /****************************************************************************
430 scan a directory to find a filename, matching without case sensitivity
432 If the name looks like a mangled name then try via the mangling functions
433 ****************************************************************************/
434 static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache)
436 void *cur_dir;
437 char *dname;
438 BOOL mangled;
439 pstring name2;
441 mangled = is_mangled(name);
443 /* handle null paths */
444 if (*path == 0)
445 path = ".";
447 if (docache && (dname = DirCacheCheck(path,name,SNUM(cnum)))) {
448 strcpy(name, dname);
449 return(True);
452 if (mangled)
453 check_mangled_stack(name);
455 /* open the directory */
456 if (!(cur_dir = OpenDir(cnum, path, True)))
458 DEBUG(3,("scan dir didn't open dir [%s]\n",path));
459 return(False);
462 /* now scan for matching names */
463 while ((dname = ReadDirName(cur_dir)))
465 if (*dname == '.' &&
466 (strequal(dname,".") || strequal(dname,"..")))
467 continue;
469 pstrcpy(name2,dname);
470 if (!name_map_mangle(name2,False,SNUM(cnum))) continue;
472 if ((mangled && mangled_equal(name,name2))
473 || fname_equal(name, name2)) /* name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra) */
475 /* we've found the file, change it's name and return */
476 if (docache) DirCacheAdd(path,name,dname,SNUM(cnum));
477 strcpy(name, dname);
478 CloseDir(cur_dir);
479 return(True);
483 CloseDir(cur_dir);
484 return(False);
487 /****************************************************************************
488 This routine is called to convert names from the dos namespace to unix
489 namespace. It needs to handle any case conversions, mangling, format
490 changes etc.
492 We assume that we have already done a chdir() to the right "root" directory
493 for this service.
495 The function will return False if some part of the name except for the last
496 part cannot be resolved
498 If the saved_last_component != 0, then the unmodified last component
499 of the pathname is returned there. This is used in an exceptional
500 case in reply_mv (so far). If saved_last_component == 0 then nothing
501 is returned there.
503 The bad_path arg is set to True if the filename walk failed. This is
504 used to pick the correct error code to return between ENOENT and ENOTDIR
505 as Windows applications depend on ERRbadpath being returned if a component
506 of a pathname does not exist.
507 ****************************************************************************/
508 BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path)
510 struct stat st;
511 char *start, *end;
512 pstring dirpath;
513 int saved_errno;
515 *dirpath = 0;
516 *bad_path = False;
518 if(saved_last_component)
519 *saved_last_component = 0;
521 /* convert to basic unix format - removing \ chars and cleaning it up */
522 unix_format(name);
523 unix_clean_name(name);
525 /* names must be relative to the root of the service - trim any leading /.
526 also trim trailing /'s */
527 trim_string(name,"/","/");
530 * Ensure saved_last_component is valid even if file exists.
532 if(saved_last_component) {
533 end = strrchr(name, '/');
534 if(end)
535 strcpy(saved_last_component, end + 1);
536 else
537 strcpy(saved_last_component, name);
540 if (!case_sensitive &&
541 (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
542 strnorm(name);
544 /* check if it's a printer file */
545 if (Connections[cnum].printer)
547 if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
549 char *s;
550 fstring name2;
551 sprintf(name2,"%.6s.XXXXXX",remote_machine);
552 /* sanitise the name */
553 for (s=name2 ; *s ; s++)
554 if (!issafe(*s)) *s = '_';
555 strcpy(name,(char *)mktemp(name2));
557 return(True);
560 /* stat the name - if it exists then we are all done! */
561 if (sys_stat(name,&st) == 0)
562 return(True);
564 saved_errno = errno;
566 DEBUG(5,("unix_convert(%s,%d)\n",name,cnum));
568 /* a special case - if we don't have any mangling chars and are case
569 sensitive then searching won't help */
570 if (case_sensitive && !is_mangled(name) &&
571 !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT))
572 return(False);
574 /* now we need to recursively match the name against the real
575 directory structure */
577 start = name;
578 while (strncmp(start,"./",2) == 0)
579 start += 2;
581 /* now match each part of the path name separately, trying the names
582 as is first, then trying to scan the directory for matching names */
583 for (;start;start = (end?end+1:(char *)NULL))
585 /* pinpoint the end of this section of the filename */
586 end = strchr(start, '/');
588 /* chop the name at this point */
589 if (end) *end = 0;
591 if(saved_last_component != 0)
592 strcpy(saved_last_component, end ? end + 1 : start);
594 /* check if the name exists up to this point */
595 if (sys_stat(name, &st) == 0)
597 /* it exists. it must either be a directory or this must be
598 the last part of the path for it to be OK */
599 if (end && !(st.st_mode & S_IFDIR))
601 /* an intermediate part of the name isn't a directory */
602 DEBUG(5,("Not a dir %s\n",start));
603 *end = '/';
604 return(False);
607 else
609 pstring rest;
611 *rest = 0;
613 /* remember the rest of the pathname so it can be restored
614 later */
615 if (end) pstrcpy(rest,end+1);
617 /* try to find this part of the path in the directory */
618 if (strchr(start,'?') || strchr(start,'*') ||
619 !scan_directory(dirpath, start, cnum, end?True:False))
621 if (end)
623 /* an intermediate part of the name can't be found */
624 DEBUG(5,("Intermediate not found %s\n",start));
625 *end = '/';
626 /* We need to return the fact that the intermediate
627 name resolution failed. This is used to return an
628 error of ERRbadpath rather than ERRbadfile. Some
629 Windows applications depend on the difference between
630 these two errors.
632 *bad_path = True;
633 return(False);
636 /* just the last part of the name doesn't exist */
637 /* we may need to strupper() or strlower() it in case
638 this conversion is being used for file creation
639 purposes */
640 /* if the filename is of mixed case then don't normalise it */
641 if (!case_preserve &&
642 (!strhasupper(start) || !strhaslower(start)))
643 strnorm(start);
645 /* check on the mangled stack to see if we can recover the
646 base of the filename */
647 if (is_mangled(start))
648 check_mangled_stack(start);
650 DEBUG(5,("New file %s\n",start));
651 return(True);
654 /* restore the rest of the string */
655 if (end)
657 strcpy(start+strlen(start)+1,rest);
658 end = start + strlen(start);
662 /* add to the dirpath that we have resolved so far */
663 if (*dirpath) strcat(dirpath,"/");
664 strcat(dirpath,start);
666 /* restore the / that we wiped out earlier */
667 if (end) *end = '/';
670 /* the name has been resolved */
671 DEBUG(5,("conversion finished %s\n",name));
672 return(True);
676 /****************************************************************************
677 normalise for DOS usage
678 ****************************************************************************/
679 static void disk_norm(int *bsize,int *dfree,int *dsize)
681 /* check if the disk is beyond the max disk size */
682 int maxdisksize = lp_maxdisksize();
683 if (maxdisksize) {
684 /* convert to blocks - and don't overflow */
685 maxdisksize = ((maxdisksize*1024)/(*bsize))*1024;
686 if (*dsize > maxdisksize) *dsize = maxdisksize;
687 if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop
688 applications getting
689 div by 0 errors */
692 while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512)
694 *dfree /= 2;
695 *dsize /= 2;
696 *bsize *= 2;
697 if (*bsize > WORDMAX )
699 *bsize = WORDMAX;
700 if (*dsize > WORDMAX)
701 *dsize = WORDMAX;
702 if (*dfree > WORDMAX)
703 *dfree = WORDMAX;
704 break;
709 /****************************************************************************
710 return number of 1K blocks available on a path and total number
711 ****************************************************************************/
712 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
714 char *df_command = lp_dfree_command();
715 int dfree_retval;
716 #ifdef QUOTAS
717 int dfreeq_retval;
718 int dfreeq = 0;
719 int bsizeq = *bsize;
720 int dsizeq = *dsize;
721 #endif
723 #ifndef NO_STATFS
724 #ifdef USE_STATVFS
725 struct statvfs fs;
726 #else
727 #ifdef ULTRIX
728 struct fs_data fs;
729 #else
730 struct statfs fs;
731 #endif
732 #endif
733 #endif
735 /* possibly use system() to get the result */
736 if (df_command && *df_command)
738 int ret;
739 pstring syscmd;
740 pstring outfile;
742 sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid());
743 sprintf(syscmd,"%s %s",df_command,path);
744 standard_sub_basic(syscmd);
746 ret = smbrun(syscmd,outfile,False);
747 DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
750 FILE *f = fopen(outfile,"r");
751 *dsize = 0;
752 *dfree = 0;
753 *bsize = 1024;
754 if (f)
756 fscanf(f,"%d %d %d",dsize,dfree,bsize);
757 fclose(f);
759 else
760 DEBUG(0,("Can't open %s\n",outfile));
763 unlink(outfile);
764 disk_norm(bsize,dfree,dsize);
765 dfree_retval = ((*bsize)/1024)*(*dfree);
766 #ifdef QUOTAS
767 /* Ensure we return the min value between the users quota and
768 what's free on the disk. Thanks to Albrecht Gebhardt
769 <albrecht.gebhardt@uni-klu.ac.at> for this fix.
771 if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
773 disk_norm(&bsizeq, &dfreeq, &dsizeq);
774 dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
775 dfree_retval = ( dfree_retval < dfreeq_retval ) ?
776 dfree_retval : dfreeq_retval ;
777 /* maybe dfree and dfreeq are calculated using different bsizes
778 so convert dfree from bsize into bsizeq */
779 /* avoid overflows due to multiplication, so do not:
780 *dfree = ((*dfree) * (*bsize)) / (bsizeq);
781 bsize and bsizeq are powers of 2 so its better to
782 to divide them getting a multiplication or division factor
783 for dfree. Rene Nieuwenhuizen (07-10-1997) */
784 if (*bsize >= bsizeq)
785 *dfree = *dfree * (*bsize / bsizeq);
786 else
787 *dfree = *dfree / (bsizeq / *bsize);
788 *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
789 *bsize = bsizeq;
790 *dsize = dsizeq;
792 #endif
793 return(dfree_retval);
796 #ifdef NO_STATFS
797 DEBUG(1,("Warning - no statfs function\n"));
798 return(1);
799 #else
800 #ifdef STATFS4
801 if (statfs(path,&fs,sizeof(fs),0) != 0)
802 #else
803 #ifdef USE_STATVFS
804 if (statvfs(path, &fs))
805 #else
806 #ifdef STATFS3
807 if (statfs(path,&fs,sizeof(fs)) == -1)
808 #else
809 if (statfs(path,&fs) == -1)
810 #endif /* STATFS3 */
811 #endif /* USE_STATVFS */
812 #endif /* STATFS4 */
814 DEBUG(3,("dfree call failed code errno=%d\n",errno));
815 *bsize = 1024;
816 *dfree = 1;
817 *dsize = 1;
818 return(((*bsize)/1024)*(*dfree));
821 #ifdef ULTRIX
822 *bsize = 1024;
823 *dfree = fs.fd_req.bfree;
824 *dsize = fs.fd_req.btot;
825 #else
826 #ifdef USE_STATVFS
827 *bsize = fs.f_frsize;
828 #else
829 #ifdef USE_F_FSIZE
830 /* eg: osf1 has f_fsize = fundamental filesystem block size,
831 f_bsize = optimal transfer block size (MX: 94-04-19) */
832 *bsize = fs.f_fsize;
833 #else
834 *bsize = fs.f_bsize;
835 #endif /* STATFS3 */
836 #endif /* USE_STATVFS */
838 #ifdef STATFS4
839 *dfree = fs.f_bfree;
840 #else
841 *dfree = fs.f_bavail;
842 #endif /* STATFS4 */
843 *dsize = fs.f_blocks;
844 #endif /* ULTRIX */
846 #if defined(SCO) || defined(ISC) || defined(MIPS)
847 *bsize = 512;
848 #endif
850 /* handle rediculous bsize values - some OSes are broken */
851 if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
853 disk_norm(bsize,dfree,dsize);
855 if (*bsize < 256)
856 *bsize = 512;
857 if ((*dsize)<1)
859 DEBUG(0,("dfree seems to be broken on your system\n"));
860 *dsize = 20*1024*1024/(*bsize);
861 *dfree = MAX(1,*dfree);
863 dfree_retval = ((*bsize)/1024)*(*dfree);
864 #ifdef QUOTAS
865 /* Ensure we return the min value between the users quota and
866 what's free on the disk. Thanks to Albrecht Gebhardt
867 <albrecht.gebhardt@uni-klu.ac.at> for this fix.
869 if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
871 disk_norm(&bsizeq, &dfreeq, &dsizeq);
872 dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
873 dfree_retval = ( dfree_retval < dfreeq_retval ) ?
874 dfree_retval : dfreeq_retval ;
875 /* maybe dfree and dfreeq are calculated using different bsizes
876 so convert dfree from bsize into bsizeq */
877 /* avoid overflows due to multiplication, so do not:
878 *dfree = ((*dfree) * (*bsize)) / (bsizeq);
879 bsize and bsizeq are powers of 2 so its better to
880 to divide them getting a multiplication or division factor
881 for dfree. Rene Nieuwenhuizen (07-10-1997) */
882 if (*bsize >= bsizeq)
883 *dfree = *dfree * (*bsize / bsizeq);
884 else
885 *dfree = *dfree / (bsizeq / *bsize);
886 *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
887 *bsize = bsizeq;
888 *dsize = dsizeq;
890 #endif
891 return(dfree_retval);
892 #endif
896 /****************************************************************************
897 wrap it to get filenames right
898 ****************************************************************************/
899 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize)
901 return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize));
906 /****************************************************************************
907 check a filename - possibly caling reducename
909 This is called by every routine before it allows an operation on a filename.
910 It does any final confirmation necessary to ensure that the filename is
911 a valid one for the user to access.
912 ****************************************************************************/
913 BOOL check_name(char *name,int cnum)
915 BOOL ret;
917 errno = 0;
919 if( IS_VETO_PATH(cnum, name))
921 DEBUG(5,("file path name %s vetoed\n",name));
922 return(0);
925 ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum)));
927 /* Check if we are allowing users to follow symlinks */
928 /* Patch from David Clerc <David.Clerc@cui.unige.ch>
929 University of Geneva */
931 #ifdef S_ISLNK
932 if (!lp_symlinks(SNUM(cnum)))
934 struct stat statbuf;
935 if ( (sys_lstat(name,&statbuf) != -1) &&
936 (S_ISLNK(statbuf.st_mode)) )
938 DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name));
939 ret=0;
942 #endif
944 if (!ret)
945 DEBUG(5,("check_name on %s failed\n",name));
947 return(ret);
950 /****************************************************************************
951 check a filename - possibly caling reducename
952 ****************************************************************************/
953 static void check_for_pipe(char *fname)
955 /* special case of pipe opens */
956 char s[10];
957 StrnCpy(s,fname,9);
958 strlower(s);
959 if (strstr(s,"pipe/"))
961 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
962 unix_ERR_class = ERRSRV;
963 unix_ERR_code = ERRaccess;
967 /****************************************************************************
968 fd support routines - attempt to do a sys_open
969 ****************************************************************************/
970 static int fd_attempt_open(char *fname, int flags, int mode)
972 int fd = sys_open(fname,flags,mode);
974 /* Fix for files ending in '.' */
975 if((fd == -1) && (errno == ENOENT) &&
976 (strchr(fname,'.')==NULL))
978 strcat(fname,".");
979 fd = sys_open(fname,flags,mode);
982 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
983 if ((fd == -1) && (errno == ENAMETOOLONG))
985 int max_len;
986 char *p = strrchr(fname, '/');
988 if (p == fname) /* name is "/xxx" */
990 max_len = pathconf("/", _PC_NAME_MAX);
991 p++;
993 else if ((p == NULL) || (p == fname))
995 p = fname;
996 max_len = pathconf(".", _PC_NAME_MAX);
998 else
1000 *p = '\0';
1001 max_len = pathconf(fname, _PC_NAME_MAX);
1002 *p = '/';
1003 p++;
1005 if (strlen(p) > max_len)
1007 char tmp = p[max_len];
1009 p[max_len] = '\0';
1010 if ((fd = sys_open(fname,flags,mode)) == -1)
1011 p[max_len] = tmp;
1014 #endif
1015 return fd;
1018 /****************************************************************************
1019 fd support routines - attempt to find an already open file by dev
1020 and inode - increments the ref_count of the returned file_fd_struct *.
1021 ****************************************************************************/
1022 static file_fd_struct *fd_get_already_open(struct stat *sbuf)
1024 int i;
1025 file_fd_struct *fd_ptr;
1027 if(sbuf == 0)
1028 return 0;
1030 for(i = 0; i <= max_file_fd_used; i++) {
1031 fd_ptr = &FileFd[i];
1032 if((fd_ptr->ref_count > 0) &&
1033 (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
1034 (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
1035 fd_ptr->ref_count++;
1036 DEBUG(3,
1037 ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
1038 i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count));
1039 return fd_ptr;
1042 return 0;
1045 /****************************************************************************
1046 fd support routines - attempt to find a empty slot in the FileFd array.
1047 Increments the ref_count of the returned entry.
1048 ****************************************************************************/
1049 static file_fd_struct *fd_get_new()
1051 int i;
1052 file_fd_struct *fd_ptr;
1054 for(i = 0; i < MAX_OPEN_FILES; i++) {
1055 fd_ptr = &FileFd[i];
1056 if(fd_ptr->ref_count == 0) {
1057 fd_ptr->dev = (uint32)-1;
1058 fd_ptr->inode = (uint32)-1;
1059 fd_ptr->fd = -1;
1060 fd_ptr->fd_readonly = -1;
1061 fd_ptr->fd_writeonly = -1;
1062 fd_ptr->real_open_flags = -1;
1063 fd_ptr->ref_count++;
1064 /* Increment max used counter if neccessary, cuts down
1065 on search time when re-using */
1066 if(i > max_file_fd_used)
1067 max_file_fd_used = i;
1068 DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n",
1069 i, fd_ptr->dev, fd_ptr->inode));
1070 return fd_ptr;
1073 DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\
1074 n"));
1075 return 0;
1078 /****************************************************************************
1079 fd support routines - attempt to re-open an already open fd as O_RDWR.
1080 Save the already open fd (we cannot close due to POSIX file locking braindamage.
1081 ****************************************************************************/
1082 static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
1084 int fd = sys_open( fname, O_RDWR, mode);
1086 if(fd == -1)
1087 return;
1089 if(fd_ptr->real_open_flags == O_RDONLY)
1090 fd_ptr->fd_readonly = fd_ptr->fd;
1091 if(fd_ptr->real_open_flags == O_WRONLY)
1092 fd_ptr->fd_writeonly = fd_ptr->fd;
1094 fd_ptr->fd = fd;
1095 fd_ptr->real_open_flags = O_RDWR;
1098 /****************************************************************************
1099 fd support routines - attempt to close the file referenced by this fd.
1100 Decrements the ref_count and returns it.
1101 ****************************************************************************/
1102 static int fd_attempt_close(file_fd_struct *fd_ptr)
1104 DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
1105 fd_ptr - &FileFd[0],
1106 fd_ptr->fd, fd_ptr->dev, fd_ptr->inode,
1107 fd_ptr->real_open_flags,
1108 fd_ptr->ref_count));
1109 if(fd_ptr->ref_count > 0) {
1110 fd_ptr->ref_count--;
1111 if(fd_ptr->ref_count == 0) {
1112 if(fd_ptr->fd != -1)
1113 close(fd_ptr->fd);
1114 if(fd_ptr->fd_readonly != -1)
1115 close(fd_ptr->fd_readonly);
1116 if(fd_ptr->fd_writeonly != -1)
1117 close(fd_ptr->fd_writeonly);
1118 fd_ptr->fd = -1;
1119 fd_ptr->fd_readonly = -1;
1120 fd_ptr->fd_writeonly = -1;
1121 fd_ptr->real_open_flags = -1;
1122 fd_ptr->dev = (uint32)-1;
1123 fd_ptr->inode = (uint32)-1;
1126 return fd_ptr->ref_count;
1129 /****************************************************************************
1130 open a file
1131 ****************************************************************************/
1132 static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
1134 extern struct current_user current_user;
1135 pstring fname;
1136 struct stat statbuf;
1137 file_fd_struct *fd_ptr;
1138 files_struct *fsp = &Files[fnum];
1140 fsp->open = False;
1141 fsp->fd_ptr = 0;
1142 fsp->granted_oplock = False;
1143 errno = EPERM;
1145 pstrcpy(fname,fname1);
1147 /* check permissions */
1148 if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
1150 DEBUG(3,("Permission denied opening %s\n",fname));
1151 check_for_pipe(fname);
1152 return;
1155 /* this handles a bug in Win95 - it doesn't say to create the file when it
1156 should */
1157 if (Connections[cnum].printer)
1158 flags |= O_CREAT;
1161 if (flags == O_WRONLY)
1162 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
1166 * Ensure we have a valid struct stat so we can search the
1167 * open fd table.
1169 if(sbuf == 0) {
1170 if(stat(fname, &statbuf) < 0) {
1171 if(errno != ENOENT) {
1172 DEBUG(3,("Error doing stat on file %s (%s)\n",
1173 fname,strerror(errno)));
1175 check_for_pipe(fname);
1176 return;
1178 sbuf = 0;
1179 } else {
1180 sbuf = &statbuf;
1185 * Check to see if we have this file already
1186 * open. If we do, just use the already open fd and increment the
1187 * reference count (fd_get_already_open increments the ref_count).
1189 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
1191 int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
1193 /* File was already open. */
1194 if((flags & O_CREAT) && (flags & O_EXCL)) {
1195 fd_ptr->ref_count--;
1196 errno = EEXIST;
1197 return;
1201 * If not opened O_RDWR try
1202 * and do that here - a chmod may have been done
1203 * between the last open and now.
1205 if(fd_ptr->real_open_flags != O_RDWR)
1206 fd_attempt_reopen(fname, mode, fd_ptr);
1209 * Ensure that if we wanted write access
1210 * it has been opened for write, and if we wanted read it
1211 * was open for read.
1213 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
1214 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
1215 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
1216 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
1217 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
1218 check_for_pipe(fname);
1219 fd_ptr->ref_count--;
1220 return;
1223 } else {
1224 int open_flags;
1225 /* We need to allocate a new file_fd_struct (this increments the
1226 ref_count). */
1227 if((fd_ptr = fd_get_new()) == 0)
1228 return;
1230 * Whatever the requested flags, attempt read/write access,
1231 * as we don't know what flags future file opens may require.
1232 * If this fails, try again with the required flags.
1233 * Even if we open read/write when only read access was
1234 * requested the setting of the can_write flag in
1235 * the file_struct will protect us from errant
1236 * write requests. We never need to worry about O_APPEND
1237 * as this is not set anywhere in Samba.
1239 fd_ptr->real_open_flags = O_RDWR;
1240 /* Set the flags as needed without the read/write modes. */
1241 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
1242 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
1244 * On some systems opening a file for R/W access on a read only
1245 * filesystems sets errno to EROFS.
1247 #ifdef EROFS
1248 if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
1249 #else /* No EROFS */
1250 if((fd_ptr->fd == -1) && (errno == EACCES)) {
1251 #endif /* EROFS */
1252 if(flags & O_WRONLY) {
1253 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
1254 fd_ptr->real_open_flags = O_WRONLY;
1255 } else {
1256 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode);
1257 fd_ptr->real_open_flags = O_RDONLY;
1262 if ((fd_ptr->fd >=0) &&
1263 Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) {
1264 pstring dname;
1265 int dum1,dum2,dum3;
1266 char *p;
1267 pstrcpy(dname,fname);
1268 p = strrchr(dname,'/');
1269 if (p) *p = 0;
1270 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
1271 lp_minprintspace(SNUM(cnum))) {
1272 fd_attempt_close(fd_ptr);
1273 fsp->fd_ptr = 0;
1274 if(fd_ptr->ref_count == 0)
1275 sys_unlink(fname);
1276 errno = ENOSPC;
1277 return;
1281 if (fd_ptr->fd < 0)
1283 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
1284 fname,strerror(errno),flags));
1285 /* Ensure the ref_count is decremented. */
1286 fd_attempt_close(fd_ptr);
1287 check_for_pipe(fname);
1288 return;
1291 if (fd_ptr->fd >= 0)
1293 if(sbuf == 0) {
1294 /* Do the fstat */
1295 if(fstat(fd_ptr->fd, &statbuf) == -1) {
1296 /* Error - backout !! */
1297 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
1298 fd_ptr->fd, fname,strerror(errno)));
1299 /* Ensure the ref_count is decremented. */
1300 fd_attempt_close(fd_ptr);
1301 return;
1303 sbuf = &statbuf;
1305 /* Set the correct entries in fd_ptr. */
1306 fd_ptr->dev = (uint32)sbuf->st_dev;
1307 fd_ptr->inode = (uint32)sbuf->st_ino;
1309 fsp->fd_ptr = fd_ptr;
1310 Connections[cnum].num_files_open++;
1311 fsp->mode = sbuf->st_mode;
1312 GetTimeOfDay(&fsp->open_time);
1313 fsp->uid = current_user.id;
1314 fsp->size = 0;
1315 fsp->pos = -1;
1316 fsp->open = True;
1317 fsp->mmap_ptr = NULL;
1318 fsp->mmap_size = 0;
1319 fsp->can_lock = True;
1320 fsp->can_read = ((flags & O_WRONLY)==0);
1321 fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
1322 fsp->share_mode = 0;
1323 fsp->print_file = Connections[cnum].printer;
1324 fsp->modified = False;
1325 fsp->granted_oplock = False;
1326 fsp->cnum = cnum;
1327 string_set(&fsp->name,dos_to_unix(fname,False));
1328 fsp->wbmpx_ptr = NULL;
1331 * If the printer is marked as postscript output a leading
1332 * file identifier to ensure the file is treated as a raw
1333 * postscript file.
1334 * This has a similar effect as CtrlD=0 in WIN.INI file.
1335 * tim@fsg.com 09/06/94
1337 if (fsp->print_file && POSTSCRIPT(cnum) &&
1338 fsp->can_write)
1340 DEBUG(3,("Writing postscript line\n"));
1341 write_file(fnum,"%!\n",3);
1344 DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
1345 timestring(),Connections[cnum].user,fname,
1346 BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write),
1347 Connections[cnum].num_files_open,fnum));
1351 #if USE_MMAP
1352 /* mmap it if read-only */
1353 if (!fsp->can_write)
1355 fsp->mmap_size = file_size(fname);
1356 fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size,
1357 PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0);
1359 if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr)
1361 DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
1362 fsp->mmap_ptr = NULL;
1365 #endif
1368 /*******************************************************************
1369 sync a file
1370 ********************************************************************/
1371 void sync_file(int fnum)
1373 #ifndef NO_FSYNC
1374 fsync(Files[fnum].fd_ptr->fd);
1375 #endif
1378 /****************************************************************************
1379 run a file if it is a magic script
1380 ****************************************************************************/
1381 static void check_magic(int fnum,int cnum)
1383 if (!*lp_magicscript(SNUM(cnum)))
1384 return;
1386 DEBUG(5,("checking magic for %s\n",Files[fnum].name));
1389 char *p;
1390 if (!(p = strrchr(Files[fnum].name,'/')))
1391 p = Files[fnum].name;
1392 else
1393 p++;
1395 if (!strequal(lp_magicscript(SNUM(cnum)),p))
1396 return;
1400 int ret;
1401 pstring magic_output;
1402 pstring fname;
1403 pstrcpy(fname,Files[fnum].name);
1405 if (*lp_magicoutput(SNUM(cnum)))
1406 pstrcpy(magic_output,lp_magicoutput(SNUM(cnum)));
1407 else
1408 sprintf(magic_output,"%s.out",fname);
1410 chmod(fname,0755);
1411 ret = smbrun(fname,magic_output,False);
1412 DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret));
1413 unlink(fname);
1418 /****************************************************************************
1419 close a file - possibly invalidating the read prediction
1421 If normal_close is 1 then this came from a normal SMBclose (or equivalent)
1422 operation otherwise it came as the result of some other operation such as
1423 the closing of the connection. In the latter case printing and
1424 magic scripts are not run
1425 ****************************************************************************/
1426 void close_file(int fnum, BOOL normal_close)
1428 files_struct *fs_p = &Files[fnum];
1429 int cnum = fs_p->cnum;
1430 uint32 dev = fs_p->fd_ptr->dev;
1431 uint32 inode = fs_p->fd_ptr->inode;
1432 int token;
1434 invalidate_read_prediction(fs_p->fd_ptr->fd);
1435 fs_p->open = False;
1436 Connections[cnum].num_files_open--;
1437 if(fs_p->wbmpx_ptr)
1439 free((char *)fs_p->wbmpx_ptr);
1440 fs_p->wbmpx_ptr = NULL;
1443 #if USE_MMAP
1444 if(fs_p->mmap_ptr)
1446 munmap(fs_p->mmap_ptr,fs_p->mmap_size);
1447 fs_p->mmap_ptr = NULL;
1449 #endif
1451 if (lp_share_modes(SNUM(cnum)))
1453 lock_share_entry( cnum, dev, inode, &token);
1454 del_share_mode(token, fnum);
1457 fd_attempt_close(fs_p->fd_ptr);
1459 if (lp_share_modes(SNUM(cnum)))
1460 unlock_share_entry( cnum, dev, inode, token);
1462 /* NT uses smbclose to start a print - weird */
1463 if (normal_close && fs_p->print_file)
1464 print_file(fnum);
1466 /* check for magic scripts */
1467 if (normal_close)
1468 check_magic(fnum,cnum);
1470 DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
1471 timestring(),Connections[cnum].user,fs_p->name,
1472 Connections[cnum].num_files_open));
1475 enum {AFAIL,AREAD,AWRITE,AALL};
1477 /*******************************************************************
1478 reproduce the share mode access table
1479 ********************************************************************/
1480 static int access_table(int new_deny,int old_deny,int old_mode,
1481 int share_pid,char *fname)
1483 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
1485 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
1486 int pid = getpid();
1487 if (old_deny == new_deny && share_pid == pid)
1488 return(AALL);
1490 if (old_mode == 0) return(AREAD);
1492 /* the new smbpub.zip spec says that if the file extension is
1493 .com, .dll, .exe or .sym then allow the open. I will force
1494 it to read-only as this seems sensible although the spec is
1495 a little unclear on this. */
1496 if ((fname = strrchr(fname,'.'))) {
1497 if (strequal(fname,".com") ||
1498 strequal(fname,".dll") ||
1499 strequal(fname,".exe") ||
1500 strequal(fname,".sym"))
1501 return(AREAD);
1504 return(AFAIL);
1507 switch (new_deny)
1509 case DENY_WRITE:
1510 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
1511 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
1512 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1513 return(AFAIL);
1514 case DENY_READ:
1515 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1516 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1517 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1518 return(AFAIL);
1519 case DENY_NONE:
1520 if (old_deny==DENY_WRITE) return(AREAD);
1521 if (old_deny==DENY_READ) return(AWRITE);
1522 if (old_deny==DENY_NONE) return(AALL);
1523 return(AFAIL);
1525 return(AFAIL);
1528 /*******************************************************************
1529 check if the share mode on a file allows it to be deleted or unlinked
1530 return True if sharing doesn't prevent the operation
1531 ********************************************************************/
1532 BOOL check_file_sharing(int cnum,char *fname)
1534 int i;
1535 int ret = False;
1536 share_mode_entry *old_shares = 0;
1537 int num_share_modes;
1538 struct stat sbuf;
1539 int token;
1540 int pid = getpid();
1541 uint32 dev, inode;
1543 if(!lp_share_modes(SNUM(cnum)))
1544 return True;
1546 if (stat(fname,&sbuf) == -1) return(True);
1548 dev = (uint32)sbuf.st_dev;
1549 inode = (uint32)sbuf.st_ino;
1551 lock_share_entry(cnum, dev, inode, &token);
1552 num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
1555 * Check if the share modes will give us access.
1558 if(num_share_modes != 0)
1560 BOOL broke_oplock;
1565 broke_oplock = False;
1566 for(i = 0; i < num_share_modes; i++)
1568 share_mode_entry *share_entry = &old_shares[i];
1571 * Break oplocks before checking share modes. See comment in
1572 * open_file_shared for details.
1573 * Check if someone has an oplock on this file. If so we must
1574 * break it before continuing.
1576 if(share_entry->op_type & BATCH_OPLOCK)
1579 DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \
1580 dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode));
1582 /* Oplock break.... */
1583 unlock_share_entry(cnum, dev, inode, token);
1584 if(request_oplock_break(share_entry, dev, inode) == False)
1586 free((char *)old_shares);
1587 DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \
1588 dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
1589 return False;
1591 lock_share_entry(cnum, dev, inode, &token);
1592 broke_oplock = True;
1593 break;
1596 /* someone else has a share lock on it, check to see
1597 if we can too */
1598 if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid))
1599 goto free_and_exit;
1601 } /* end for */
1603 if(broke_oplock)
1605 free((char *)old_shares);
1606 num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
1608 } while(broke_oplock);
1611 /* XXXX exactly what share mode combinations should be allowed for
1612 deleting/renaming? */
1613 /* If we got here then either there were no share modes or
1614 all share modes were DENY_DOS and the pid == getpid() */
1615 ret = True;
1617 free_and_exit:
1619 unlock_share_entry(cnum, dev, inode, token);
1620 if(old_shares != NULL)
1621 free((char *)old_shares);
1622 return(ret);
1625 /****************************************************************************
1626 C. Hoch 11/22/95
1627 Helper for open_file_shared.
1628 Truncate a file after checking locking; close file if locked.
1629 **************************************************************************/
1630 static void truncate_unless_locked(int fnum, int cnum, int token,
1631 BOOL *share_locked)
1633 if (Files[fnum].can_write){
1634 if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
1635 /* If share modes are in force for this connection we
1636 have the share entry locked. Unlock it before closing. */
1637 if (*share_locked && lp_share_modes(SNUM(cnum)))
1638 unlock_share_entry( cnum, Files[fnum].fd_ptr->dev,
1639 Files[fnum].fd_ptr->inode, token);
1640 close_file(fnum,False);
1641 /* Share mode no longer locked. */
1642 *share_locked = False;
1643 errno = EACCES;
1644 unix_ERR_class = ERRDOS;
1645 unix_ERR_code = ERRlock;
1647 else
1648 ftruncate(Files[fnum].fd_ptr->fd,0);
1652 /****************************************************************************
1653 check if we can open a file with a share mode
1654 ****************************************************************************/
1655 int check_share_mode( share_mode_entry *share, int deny_mode, char *fname,
1656 BOOL fcbopen, int *flags)
1658 int old_open_mode = share->share_mode &0xF;
1659 int old_deny_mode = (share->share_mode >>4)&7;
1661 if (old_deny_mode > 4 || old_open_mode > 2)
1663 DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
1664 deny_mode,old_deny_mode,old_open_mode,fname));
1665 return False;
1669 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1670 share->pid,fname);
1672 if ((access_allowed == AFAIL) ||
1673 (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) ||
1674 (access_allowed == AREAD && *flags == O_WRONLY) ||
1675 (access_allowed == AWRITE && *flags == O_RDONLY))
1677 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
1678 deny_mode,old_deny_mode,old_open_mode,
1679 share->pid,fname, access_allowed));
1680 return False;
1683 if (access_allowed == AREAD)
1684 *flags = O_RDONLY;
1686 if (access_allowed == AWRITE)
1687 *flags = O_WRONLY;
1690 return True;
1693 /****************************************************************************
1694 open a file with a share mode
1695 ****************************************************************************/
1696 void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
1697 int mode,int oplock_request, int *Access,int *action)
1699 files_struct *fs_p = &Files[fnum];
1700 int flags=0;
1701 int flags2=0;
1702 int deny_mode = (share_mode>>4)&7;
1703 struct stat sbuf;
1704 BOOL file_existed = file_exist(fname,&sbuf);
1705 BOOL share_locked = False;
1706 BOOL fcbopen = False;
1707 int token;
1708 uint32 dev = 0;
1709 uint32 inode = 0;
1710 int num_share_modes = 0;
1712 fs_p->open = False;
1713 fs_p->fd_ptr = 0;
1715 /* this is for OS/2 EAs - try and say we don't support them */
1716 if (strstr(fname,".+,;=[]."))
1718 unix_ERR_class = ERRDOS;
1719 /* OS/2 Workplace shell fix may be main code stream in a later release. */
1720 #ifdef OS2_WPS_FIX
1721 unix_ERR_code = ERRcannotopen;
1722 #else /* OS2_WPS_FIX */
1723 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
1724 #endif /* OS2_WPS_FIX */
1726 return;
1729 if ((ofun & 0x3) == 0 && file_existed)
1731 errno = EEXIST;
1732 return;
1735 if (ofun & 0x10)
1736 flags2 |= O_CREAT;
1737 if ((ofun & 0x3) == 2)
1738 flags2 |= O_TRUNC;
1740 /* note that we ignore the append flag as
1741 append does not mean the same thing under dos and unix */
1743 switch (share_mode&0xF)
1745 case 1:
1746 flags = O_WRONLY;
1747 break;
1748 case 0xF:
1749 fcbopen = True;
1750 flags = O_RDWR;
1751 break;
1752 case 2:
1753 flags = O_RDWR;
1754 break;
1755 default:
1756 flags = O_RDONLY;
1757 break;
1760 if (flags != O_RDONLY && file_existed &&
1761 (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf))))
1763 if (!fcbopen)
1765 errno = EACCES;
1766 return;
1768 flags = O_RDONLY;
1771 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB)
1773 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
1774 errno = EINVAL;
1775 return;
1778 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
1780 if (lp_share_modes(SNUM(cnum)))
1782 int i;
1783 share_mode_entry *old_shares = 0;
1785 if (file_existed)
1787 dev = (uint32)sbuf.st_dev;
1788 inode = (uint32)sbuf.st_ino;
1789 lock_share_entry(cnum, dev, inode, &token);
1790 share_locked = True;
1791 num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
1795 * Check if the share modes will give us access.
1798 if(share_locked && (num_share_modes != 0))
1800 BOOL broke_oplock;
1805 broke_oplock = False;
1806 for(i = 0; i < num_share_modes; i++)
1808 share_mode_entry *share_entry = &old_shares[i];
1811 * By observation of NetBench, oplocks are broken *before* share
1812 * modes are checked. This allows a file to be closed by the client
1813 * if the share mode would deny access and the client has an oplock.
1814 * Check if someone has an oplock on this file. If so we must break
1815 * it before continuing.
1817 if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
1820 DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \
1821 dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode));
1823 /* Oplock break.... */
1824 unlock_share_entry(cnum, dev, inode, token);
1825 if(request_oplock_break(share_entry, dev, inode) == False)
1827 free((char *)old_shares);
1828 DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \
1829 dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
1830 errno = EACCES;
1831 unix_ERR_class = ERRDOS;
1832 unix_ERR_code = ERRbadshare;
1833 return;
1835 lock_share_entry(cnum, dev, inode, &token);
1836 broke_oplock = True;
1837 break;
1840 /* someone else has a share lock on it, check to see
1841 if we can too */
1842 if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False)
1844 free((char *)old_shares);
1845 unlock_share_entry(cnum, dev, inode, token);
1846 errno = EACCES;
1847 unix_ERR_class = ERRDOS;
1848 unix_ERR_code = ERRbadshare;
1849 return;
1852 } /* end for */
1854 if(broke_oplock)
1856 free((char *)old_shares);
1857 num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
1859 } while(broke_oplock);
1862 if(old_shares != 0)
1863 free((char *)old_shares);
1866 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
1867 flags,flags2,mode));
1869 open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
1870 if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
1872 flags = O_RDONLY;
1873 open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
1876 if (fs_p->open)
1878 int open_mode=0;
1880 if((share_locked == False) && lp_share_modes(SNUM(cnum)))
1882 /* We created the file - thus we must now lock the share entry before creating it. */
1883 dev = fs_p->fd_ptr->dev;
1884 inode = fs_p->fd_ptr->inode;
1885 lock_share_entry(cnum, dev, inode, &token);
1886 share_locked = True;
1889 switch (flags)
1891 case O_RDONLY:
1892 open_mode = 0;
1893 break;
1894 case O_RDWR:
1895 open_mode = 2;
1896 break;
1897 case O_WRONLY:
1898 open_mode = 1;
1899 break;
1902 fs_p->share_mode = (deny_mode<<4) | open_mode;
1904 if (Access)
1905 (*Access) = open_mode;
1907 if (action)
1909 if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
1910 if (!file_existed) *action = 2;
1911 if (file_existed && (flags2 & O_TRUNC)) *action = 3;
1913 /* We must create the share mode entry before truncate as
1914 truncate can fail due to locking and have to close the
1915 file (which expects the share_mode_entry to be there).
1917 if (lp_share_modes(SNUM(cnum)))
1919 uint16 port = 0;
1920 /* JRA. Currently this only services Exlcusive and batch
1921 oplocks (no other opens on this file). This needs to
1922 be extended to level II oplocks (multiple reader
1923 oplocks). */
1925 if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum)))
1927 fs_p->granted_oplock = True;
1928 global_oplocks_open++;
1929 port = oplock_port;
1931 DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \
1932 dev = %x, inode = %x\n", oplock_request, fname, dev, inode));
1935 else
1937 port = 0;
1938 oplock_request = 0;
1940 set_share_mode(token, fnum, port, oplock_request);
1943 if ((flags2&O_TRUNC) && file_existed)
1944 truncate_unless_locked(fnum,cnum,token,&share_locked);
1947 if (share_locked && lp_share_modes(SNUM(cnum)))
1948 unlock_share_entry( cnum, dev, inode, token);
1951 /****************************************************************************
1952 seek a file. Try to avoid the seek if possible
1953 ****************************************************************************/
1954 int seek_file(int fnum,uint32 pos)
1956 uint32 offset = 0;
1957 if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
1958 offset = 3;
1960 Files[fnum].pos = (int)(lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET)
1961 - offset);
1962 return(Files[fnum].pos);
1965 /****************************************************************************
1966 read from a file
1967 ****************************************************************************/
1968 int read_file(int fnum,char *data,uint32 pos,int n)
1970 int ret=0,readret;
1972 if (!Files[fnum].can_write)
1974 ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n);
1976 data += ret;
1977 n -= ret;
1978 pos += ret;
1981 #if USE_MMAP
1982 if (Files[fnum].mmap_ptr)
1984 int num = MIN(n,(int)(Files[fnum].mmap_size-pos));
1985 if (num > 0)
1987 memcpy(data,Files[fnum].mmap_ptr+pos,num);
1988 data += num;
1989 pos += num;
1990 n -= num;
1991 ret += num;
1994 #endif
1996 if (n <= 0)
1997 return(ret);
1999 if (seek_file(fnum,pos) != pos)
2001 DEBUG(3,("Failed to seek to %d\n",pos));
2002 return(ret);
2005 if (n > 0) {
2006 readret = read(Files[fnum].fd_ptr->fd,data,n);
2007 if (readret > 0) ret += readret;
2010 return(ret);
2014 /****************************************************************************
2015 write to a file
2016 ****************************************************************************/
2017 int write_file(int fnum,char *data,int n)
2019 if (!Files[fnum].can_write) {
2020 errno = EPERM;
2021 return(0);
2024 if (!Files[fnum].modified) {
2025 struct stat st;
2026 Files[fnum].modified = True;
2027 if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) {
2028 int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st);
2029 if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) {
2030 dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st);
2035 return(write_data(Files[fnum].fd_ptr->fd,data,n));
2039 /****************************************************************************
2040 load parameters specific to a connection/service
2041 ****************************************************************************/
2042 BOOL become_service(int cnum,BOOL do_chdir)
2044 extern char magic_char;
2045 static int last_cnum = -1;
2046 int snum;
2048 if (!OPEN_CNUM(cnum))
2050 last_cnum = -1;
2051 return(False);
2054 Connections[cnum].lastused = smb_last_time;
2056 snum = SNUM(cnum);
2058 if (do_chdir &&
2059 ChDir(Connections[cnum].connectpath) != 0 &&
2060 ChDir(Connections[cnum].origpath) != 0)
2062 DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
2063 Connections[cnum].connectpath,cnum));
2064 return(False);
2067 if (cnum == last_cnum)
2068 return(True);
2070 last_cnum = cnum;
2072 case_default = lp_defaultcase(snum);
2073 case_preserve = lp_preservecase(snum);
2074 short_case_preserve = lp_shortpreservecase(snum);
2075 case_mangle = lp_casemangle(snum);
2076 case_sensitive = lp_casesensitive(snum);
2077 magic_char = lp_magicchar(snum);
2078 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
2079 return(True);
2083 /****************************************************************************
2084 find a service entry
2085 ****************************************************************************/
2086 int find_service(char *service)
2088 int iService;
2090 string_sub(service,"\\","/");
2092 iService = lp_servicenumber(service);
2094 /* now handle the special case of a home directory */
2095 if (iService < 0)
2097 char *phome_dir = get_home_dir(service);
2098 DEBUG(3,("checking for home directory %s gave %s\n",service,
2099 phome_dir?phome_dir:"(NULL)"));
2100 if (phome_dir)
2102 int iHomeService;
2103 if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
2105 lp_add_home(service,iHomeService,phome_dir);
2106 iService = lp_servicenumber(service);
2111 /* If we still don't have a service, attempt to add it as a printer. */
2112 if (iService < 0)
2114 int iPrinterService;
2116 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
2118 char *pszTemp;
2120 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
2121 pszTemp = PRINTCAP;
2122 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
2124 DEBUG(3,("%s is a valid printer name\n", service));
2125 DEBUG(3,("adding %s as a printer service\n", service));
2126 lp_add_printer(service,iPrinterService);
2127 iService = lp_servicenumber(service);
2128 if (iService < 0)
2129 DEBUG(0,("failed to add %s as a printer service!\n", service));
2131 else
2132 DEBUG(3,("%s is not a valid printer name\n", service));
2136 /* just possibly it's a default service? */
2137 if (iService < 0)
2139 char *defservice = lp_defaultservice();
2140 if (defservice && *defservice && !strequal(defservice,service)) {
2141 iService = find_service(defservice);
2142 if (iService >= 0) {
2143 string_sub(service,"_","/");
2144 iService = lp_add_service(service,iService);
2149 if (iService >= 0)
2150 if (!VALID_SNUM(iService))
2152 DEBUG(0,("Invalid snum %d for %s\n",iService,service));
2153 iService = -1;
2156 if (iService < 0)
2157 DEBUG(3,("find_service() failed to find service %s\n", service));
2159 return (iService);
2163 /****************************************************************************
2164 create an error packet from a cached error.
2165 ****************************************************************************/
2166 int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
2168 write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
2170 int32 eclass = wbmpx->wr_errclass;
2171 int32 err = wbmpx->wr_error;
2173 /* We can now delete the auxiliary struct */
2174 free((char *)wbmpx);
2175 Files[fnum].wbmpx_ptr = NULL;
2176 return error_packet(inbuf,outbuf,eclass,err,line);
2180 struct
2182 int unixerror;
2183 int smbclass;
2184 int smbcode;
2185 } unix_smb_errmap[] =
2187 {EPERM,ERRDOS,ERRnoaccess},
2188 {EACCES,ERRDOS,ERRnoaccess},
2189 {ENOENT,ERRDOS,ERRbadfile},
2190 {ENOTDIR,ERRDOS,ERRbadpath},
2191 {EIO,ERRHRD,ERRgeneral},
2192 {EBADF,ERRSRV,ERRsrverror},
2193 {EINVAL,ERRSRV,ERRsrverror},
2194 {EEXIST,ERRDOS,ERRfilexists},
2195 {ENFILE,ERRDOS,ERRnofids},
2196 {EMFILE,ERRDOS,ERRnofids},
2197 {ENOSPC,ERRHRD,ERRdiskfull},
2198 #ifdef EDQUOT
2199 {EDQUOT,ERRHRD,ERRdiskfull},
2200 #endif
2201 #ifdef ENOTEMPTY
2202 {ENOTEMPTY,ERRDOS,ERRnoaccess},
2203 #endif
2204 #ifdef EXDEV
2205 {EXDEV,ERRDOS,ERRdiffdevice},
2206 #endif
2207 {EROFS,ERRHRD,ERRnowrite},
2208 {0,0,0}
2211 /****************************************************************************
2212 create an error packet from errno
2213 ****************************************************************************/
2214 int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
2216 int eclass=def_class;
2217 int ecode=def_code;
2218 int i=0;
2220 if (unix_ERR_class != SUCCESS)
2222 eclass = unix_ERR_class;
2223 ecode = unix_ERR_code;
2224 unix_ERR_class = SUCCESS;
2225 unix_ERR_code = 0;
2227 else
2229 while (unix_smb_errmap[i].smbclass != 0)
2231 if (unix_smb_errmap[i].unixerror == errno)
2233 eclass = unix_smb_errmap[i].smbclass;
2234 ecode = unix_smb_errmap[i].smbcode;
2235 break;
2237 i++;
2241 return(error_packet(inbuf,outbuf,eclass,ecode,line));
2245 /****************************************************************************
2246 create an error packet. Normally called using the ERROR() macro
2247 ****************************************************************************/
2248 int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
2250 int outsize = set_message(outbuf,0,0,True);
2251 int cmd;
2252 cmd = CVAL(inbuf,smb_com);
2254 CVAL(outbuf,smb_rcls) = error_class;
2255 SSVAL(outbuf,smb_err,error_code);
2257 DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
2258 timestring(),
2259 line,
2260 (int)CVAL(inbuf,smb_com),
2261 smb_fn_name(CVAL(inbuf,smb_com)),
2262 error_class,
2263 error_code));
2265 if (errno != 0)
2266 DEBUG(3,("error string = %s\n",strerror(errno)));
2268 return(outsize);
2272 #ifndef SIGCLD_IGNORE
2273 /****************************************************************************
2274 this prevents zombie child processes
2275 ****************************************************************************/
2276 static int sig_cld()
2278 static int depth = 0;
2279 if (depth != 0)
2281 DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
2282 depth=0;
2283 return(0);
2285 depth++;
2287 BlockSignals(True,SIGCLD);
2288 DEBUG(5,("got SIGCLD\n"));
2290 #ifdef USE_WAITPID
2291 while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
2292 #endif
2294 /* Stop zombies */
2295 /* Stevens, Adv. Unix Prog. says that on system V you must call
2296 wait before reinstalling the signal handler, because the kernel
2297 calls the handler from within the signal-call when there is a
2298 child that has exited. This would lead to an infinite recursion
2299 if done vice versa. */
2301 #ifndef DONT_REINSTALL_SIG
2302 #ifdef SIGCLD_IGNORE
2303 signal(SIGCLD, SIG_IGN);
2304 #else
2305 signal(SIGCLD, SIGNAL_CAST sig_cld);
2306 #endif
2307 #endif
2309 #ifndef USE_WAITPID
2310 while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
2311 #endif
2312 depth--;
2313 BlockSignals(False,SIGCLD);
2314 return 0;
2316 #endif
2318 /****************************************************************************
2319 this is called when the client exits abruptly
2320 **************************************************************************/
2321 static int sig_pipe()
2323 struct cli_state *cli;
2324 BlockSignals(True,SIGPIPE);
2326 if ((cli = server_client()) && cli->initialised) {
2327 DEBUG(3,("lost connection to password server\n"));
2328 cli_shutdown(cli);
2329 #ifndef DONT_REINSTALL_SIG
2330 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2331 #endif
2332 BlockSignals(False,SIGPIPE);
2333 return 0;
2336 exit_server("Got sigpipe\n");
2337 return(0);
2340 /****************************************************************************
2341 open the socket communication
2342 ****************************************************************************/
2343 static BOOL open_sockets(BOOL is_daemon,int port)
2345 extern int Client;
2347 if (is_daemon)
2349 int s;
2350 struct sockaddr addr;
2351 int in_addrlen = sizeof(addr);
2353 /* Stop zombies */
2354 #ifdef SIGCLD_IGNORE
2355 signal(SIGCLD, SIG_IGN);
2356 #else
2357 signal(SIGCLD, SIGNAL_CAST sig_cld);
2358 #endif
2360 /* open an incoming socket */
2361 s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
2362 if (s == -1)
2363 return(False);
2365 /* ready to listen */
2366 if (listen(s, 5) == -1)
2368 DEBUG(0,("listen: %s\n",strerror(errno)));
2369 close(s);
2370 return False;
2373 if(atexit_set == 0)
2374 atexit(killkids);
2376 /* now accept incoming connections - forking a new process
2377 for each incoming connection */
2378 DEBUG(2,("waiting for a connection\n"));
2379 while (1)
2381 Client = accept(s,&addr,&in_addrlen);
2383 if (Client == -1 && errno == EINTR)
2384 continue;
2386 if (Client == -1)
2388 DEBUG(0,("accept: %s\n",strerror(errno)));
2389 continue;
2392 #ifdef NO_FORK_DEBUG
2393 #ifndef NO_SIGNAL_TEST
2394 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2395 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2396 #endif
2397 return True;
2398 #else
2399 if (Client != -1 && fork()==0)
2401 /* Child code ... */
2402 #ifndef NO_SIGNAL_TEST
2403 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2404 signal(SIGCLD, SIGNAL_CAST SIG_DFL);
2405 #endif
2406 /* close the listening socket */
2407 close(s);
2409 /* close our standard file descriptors */
2410 close_low_fds();
2411 am_parent = 0;
2413 set_socket_options(Client,"SO_KEEPALIVE");
2414 set_socket_options(Client,user_socket_options);
2416 /* Reset global variables in util.c so that
2417 client substitutions will be done correctly
2418 in the process.
2420 reset_globals_after_fork();
2421 return True;
2423 close(Client); /* The parent doesn't need this socket */
2424 #endif
2427 else
2429 /* We will abort gracefully when the client or remote system
2430 goes away */
2431 #ifndef NO_SIGNAL_TEST
2432 signal(SIGPIPE, SIGNAL_CAST sig_pipe);
2433 #endif
2434 Client = dup(0);
2436 /* close our standard file descriptors */
2437 close_low_fds();
2439 set_socket_options(Client,"SO_KEEPALIVE");
2440 set_socket_options(Client,user_socket_options);
2443 return True;
2446 /****************************************************************************
2447 process an smb from the client - split out from the process() code so
2448 it can be used by the oplock break code.
2449 ****************************************************************************/
2451 static void process_smb(char *inbuf, char *outbuf)
2453 extern int Client;
2454 static int trans_num;
2455 int msg_type = CVAL(inbuf,0);
2456 int32 len = smb_len(inbuf);
2457 int nread = len + 4;
2459 if (trans_num == 0) {
2460 /* on the first packet, check the global hosts allow/ hosts
2461 deny parameters before doing any parsing of the packet
2462 passed to us by the client. This prevents attacks on our
2463 parsing code from hosts not in the hosts allow list */
2464 if (!check_access(-1)) {
2465 /* send a negative session response "not listining on calling
2466 name" */
2467 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
2468 DEBUG(1,("%s Connection denied from %s\n",
2469 timestring(),client_addr()));
2470 send_smb(Client,(char *)buf);
2471 exit_server("connection denied");
2475 DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
2476 DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
2478 #ifdef WITH_VTP
2479 if(trans_num == 1 && VT_Check(inbuf))
2481 VT_Process();
2482 return;
2484 #endif
2486 if (msg_type == 0)
2487 show_msg(inbuf);
2489 nread = construct_reply(inbuf,outbuf,nread,max_send);
2491 if(nread > 0)
2493 if (CVAL(outbuf,0) == 0)
2494 show_msg(outbuf);
2496 if (nread != smb_len(outbuf) + 4)
2498 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
2499 nread, smb_len(outbuf)));
2501 else
2502 send_smb(Client,outbuf);
2504 trans_num++;
2507 /****************************************************************************
2508 open the oplock IPC socket communication
2509 ****************************************************************************/
2510 static BOOL open_oplock_ipc()
2512 struct sockaddr_in sock_name;
2513 int len = sizeof(sock_name);
2515 DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n"));
2517 /* Open a lookback UDP socket on a random port. */
2518 oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK));
2519 if (oplock_sock == -1)
2521 DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \
2522 address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno)));
2523 oplock_port = 0;
2524 return(False);
2527 /* Find out the transient UDP port we have been allocated. */
2528 if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0)
2530 DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n",
2531 strerror(errno)));
2532 close(oplock_sock);
2533 oplock_sock = -1;
2534 oplock_port = 0;
2535 return False;
2537 oplock_port = ntohs(sock_name.sin_port);
2539 DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n",
2540 getpid(), oplock_port));
2542 return True;
2545 /****************************************************************************
2546 process an oplock break message.
2547 ****************************************************************************/
2548 static BOOL process_local_message(int sock, char *buffer, int buf_size)
2550 int32 msg_len;
2551 int16 from_port;
2552 char *msg_start;
2554 msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET);
2555 from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET);
2557 msg_start = &buffer[UDP_CMD_HEADER_LEN];
2559 DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n",
2560 msg_len, from_port));
2562 /* Switch on message command - currently OPLOCK_BREAK_CMD is the
2563 only valid request. */
2565 switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET))
2567 case OPLOCK_BREAK_CMD:
2568 /* Ensure that the msg length is correct. */
2569 if(msg_len != OPLOCK_BREAK_MSG_LEN)
2571 DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, \
2572 should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
2573 return False;
2576 uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
2577 uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
2578 uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
2579 struct timeval tval;
2580 struct sockaddr_in toaddr;
2582 tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET);
2583 tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET);
2585 DEBUG(5,("process_local_message: oplock break request from \
2586 pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
2589 * If we have no record of any currently open oplocks,
2590 * it's not an error, as a close command may have
2591 * just been issued on the file that was oplocked.
2592 * Just return success in this case.
2595 if(global_oplocks_open != 0)
2597 if(oplock_break(dev, inode, &tval) == False)
2599 DEBUG(0,("process_local_message: oplock break failed - \
2600 not returning udp message.\n"));
2601 return False;
2604 else
2606 DEBUG(3,("process_local_message: oplock break requested with no outstanding \
2607 oplocks. Returning success.\n"));
2610 /* Send the message back after OR'ing in the 'REPLY' bit. */
2611 SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY);
2613 bzero((char *)&toaddr,sizeof(toaddr));
2614 toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2615 toaddr.sin_port = htons(from_port);
2616 toaddr.sin_family = AF_INET;
2618 if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
2619 (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0)
2621 DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n",
2622 remotepid, strerror(errno)));
2623 return False;
2626 DEBUG(5,("process_local_message: oplock break reply sent to \
2627 pid %d, port %d, for file dev = %x, inode = %x\n", remotepid,
2628 from_port, dev, inode));
2631 break;
2633 * Keep this as a debug case - eventually we can remove it.
2635 case 0x8001:
2636 DEBUG(0,("process_local_message: Received unsolicited break \
2637 reply - dumping info.\n"));
2639 if(msg_len != OPLOCK_BREAK_MSG_LEN)
2641 DEBUG(0,("process_local_message: ubr: incorrect length for reply \
2642 (was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
2643 return False;
2647 uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
2648 uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
2649 uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
2651 DEBUG(0,("process_local_message: unsolicited oplock break reply from \
2652 pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
2655 return False;
2657 default:
2658 DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n",
2659 (unsigned int)SVAL(msg_start,0)));
2660 return False;
2662 return True;
2665 /****************************************************************************
2666 Process an oplock break directly.
2667 ****************************************************************************/
2668 BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval)
2670 extern int Client;
2671 static char *inbuf = NULL;
2672 static char *outbuf = NULL;
2673 files_struct *fsp = NULL;
2674 int fnum;
2675 time_t start_time;
2676 BOOL shutdown_server = False;
2678 DEBUG(5,("oplock_break: called for dev = %x, inode = %x. Current \
2679 global_oplocks_open = %d\n", dev, inode, global_oplocks_open));
2681 if(inbuf == NULL)
2683 inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2684 if(inbuf == NULL) {
2685 DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
2686 return False;
2688 outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
2689 if(outbuf == NULL) {
2690 DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
2691 free(inbuf);
2692 inbuf = NULL;
2693 return False;
2697 /* We need to search the file open table for the
2698 entry containing this dev and inode, and ensure
2699 we have an oplock on it. */
2700 for( fnum = 0; fnum < MAX_OPEN_FILES; fnum++)
2702 if(OPEN_FNUM(fnum))
2704 fsp = &Files[fnum];
2705 if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode) &&
2706 (fsp->open_time.tv_sec == tval->tv_sec) &&
2707 (fsp->open_time.tv_usec == tval->tv_usec))
2708 break;
2712 if(fsp == NULL)
2714 /* The file could have been closed in the meantime - return success. */
2715 DEBUG(3,("oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \
2716 allowing break to succeed.\n", dev, inode, fnum));
2717 return True;
2720 /* Ensure we have an oplock on the file */
2722 /* There is a potential race condition in that an oplock could
2723 have been broken due to another udp request, and yet there are
2724 still oplock break messages being sent in the udp message
2725 queue for this file. So return true if we don't have an oplock,
2726 as we may have just freed it.
2729 if(!fsp->granted_oplock)
2731 DEBUG(3,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \
2732 Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode));
2733 return True;
2736 /* Now comes the horrid part. We must send an oplock break to the client,
2737 and then process incoming messages until we get a close or oplock release.
2740 /* Prepare the SMBlockingX message. */
2741 bzero(outbuf,smb_size);
2742 set_message(outbuf,8,0,True);
2744 SCVAL(outbuf,smb_com,SMBlockingX);
2745 SSVAL(outbuf,smb_tid,fsp->cnum);
2746 SSVAL(outbuf,smb_pid,0xFFFF);
2747 SSVAL(outbuf,smb_uid,0);
2748 SSVAL(outbuf,smb_mid,0xFFFF);
2749 SCVAL(outbuf,smb_vwv0,0xFF);
2750 SSVAL(outbuf,smb_vwv2,fnum);
2751 SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE);
2752 /* Change this when we have level II oplocks. */
2753 SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE);
2755 send_smb(Client, outbuf);
2757 global_oplock_break = True;
2759 /* Process incoming messages. */
2761 /* JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT
2762 seconds we should just die.... */
2764 start_time = time(NULL);
2766 while(OPEN_FNUM(fnum) && fsp->granted_oplock)
2768 if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False)
2771 * Die if we got an error.
2774 if (smb_read_error == READ_EOF)
2775 DEBUG(0,("oplock_break: end of file from client\n"));
2777 if (smb_read_error == READ_ERROR)
2778 DEBUG(0,("oplock_break: receive_smb error (%s)\n",
2779 strerror(errno)));
2781 if (smb_read_error == READ_TIMEOUT)
2782 DEBUG(0,("oplock_break: receive_smb timed out after %d seconds.\n",
2783 OPLOCK_BREAK_TIMEOUT));
2785 DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \
2786 inode = %x).\n", fsp->name, fnum, dev, inode));
2787 shutdown_server = True;
2788 break;
2790 process_smb(inbuf, outbuf);
2792 /* We only need this in case a readraw crossed on the wire. */
2793 if(global_oplock_break)
2794 global_oplock_break = False;
2797 * Die if we go over the time limit.
2800 if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT)
2802 DEBUG(0,("oplock_break: no break received from client within \
2803 %d seconds.\n", OPLOCK_BREAK_TIMEOUT));
2804 DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \
2805 inode = %x).\n", fsp->name, fnum, dev, inode));
2806 shutdown_server = True;
2807 break;
2812 * If the client did not respond we must die.
2815 if(shutdown_server)
2817 DEBUG(0,("oplock_break: client failure in break - shutting down this smbd.\n"));
2818 close_sockets();
2819 close(oplock_sock);
2820 exit_server("oplock break failure");
2823 if(OPEN_FNUM(fnum))
2825 /* The lockingX reply will have removed the oplock flag
2826 from the sharemode. */
2827 /* Paranoia.... */
2828 fsp->granted_oplock = False;
2831 global_oplocks_open--;
2833 /* Santity check - remove this later. JRA */
2834 if(global_oplocks_open < 0)
2836 DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n",
2837 global_oplocks_open));
2838 exit_server("oplock_break: global_oplocks_open < 0");
2841 DEBUG(5,("oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \
2842 global_oplocks_open = %d\n", fnum, dev, inode, global_oplocks_open));
2844 return True;
2847 /****************************************************************************
2848 Send an oplock break message to another smbd process. If the oplock is held
2849 by the local smbd then call the oplock break function directly.
2850 ****************************************************************************/
2852 BOOL request_oplock_break(share_mode_entry *share_entry,
2853 uint32 dev, uint32 inode)
2855 char op_break_msg[OPLOCK_BREAK_MSG_LEN];
2856 struct sockaddr_in addr_out;
2857 int pid = getpid();
2859 if(pid == share_entry->pid)
2861 /* We are breaking our own oplock, make sure it's us. */
2862 if(share_entry->op_port != oplock_port)
2864 DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \
2865 should be %d\n", pid, share_entry->op_port, oplock_port));
2866 return False;
2869 DEBUG(5,("request_oplock_break: breaking our own oplock\n"));
2871 /* Call oplock break direct. */
2872 return oplock_break(dev, inode, &share_entry->time);
2875 /* We need to send a OPLOCK_BREAK_CMD message to the
2876 port in the share mode entry. */
2878 SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD);
2879 SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid);
2880 SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev);
2881 SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode);
2882 SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec);
2883 SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec);
2885 /* set the address and port */
2886 bzero((char *)&addr_out,sizeof(addr_out));
2887 addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2888 addr_out.sin_port = htons( share_entry->op_port );
2889 addr_out.sin_family = AF_INET;
2891 DEBUG(3,("request_oplock_break: sending a oplock break message to pid %d on port %d \
2892 for dev = %x, inode = %x\n", share_entry->pid, share_entry->op_port, dev, inode));
2894 if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0,
2895 (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0)
2897 DEBUG(0,("request_oplock_break: failed when sending a oplock break message \
2898 to pid %d on port %d for dev = %x, inode = %x. Error was %s\n",
2899 share_entry->pid, share_entry->op_port, dev, inode,
2900 strerror(errno)));
2901 return False;
2905 * Now we must await the oplock broken message coming back
2906 * from the target smbd process. Timeout if it fails to
2907 * return in OPLOCK_BREAK_TIMEOUT seconds.
2908 * While we get messages that aren't ours, loop.
2911 while(1)
2913 char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN];
2914 int32 reply_msg_len;
2915 int16 reply_from_port;
2916 char *reply_msg_start;
2918 if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply),
2919 OPLOCK_BREAK_TIMEOUT * 1000) == False)
2921 if(smb_read_error == READ_TIMEOUT)
2922 DEBUG(0,("request_oplock_break: no response received to oplock break request to \
2923 pid %d on port %d for dev = %x, inode = %x\n", share_entry->pid,
2924 share_entry->op_port, dev, inode));
2925 else
2926 DEBUG(0,("request_oplock_break: error in response received to oplock break request to \
2927 pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid,
2928 share_entry->op_port, dev, inode, strerror(errno)));
2929 return False;
2933 * If the response we got was not an answer to our message, but
2934 * was a completely different request, push it onto the pending
2935 * udp message stack so that we can deal with it in the main loop.
2936 * It may be another oplock break request to us.
2940 * Local note from JRA. There exists the possibility of a denial
2941 * of service attack here by allowing non-root processes running
2942 * on a local machine sending many of these pending messages to
2943 * a smbd port. Currently I'm not sure how to restrict the messages
2944 * I will queue (although I could add a limit to the queue) to
2945 * those received by root processes only. There should be a
2946 * way to make this bulletproof....
2949 reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET);
2950 reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET);
2952 reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN];
2954 if(reply_msg_len != OPLOCK_BREAK_MSG_LEN)
2956 /* Ignore it. */
2957 DEBUG(0,("request_oplock_break: invalid message length received. Ignoring\n"));
2958 continue;
2961 if(((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) == 0) ||
2962 (reply_from_port != share_entry->op_port) ||
2963 (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET],
2964 &op_break_msg[OPLOCK_BREAK_PID_OFFSET],
2965 OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) != 0))
2967 DEBUG(3,("request_oplock_break: received other message whilst awaiting \
2968 oplock break response from pid %d on port %d for dev = %x, inode = %x.\n",
2969 share_entry->pid, share_entry->op_port, dev, inode));
2970 if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False)
2971 return False;
2972 continue;
2975 break;
2978 DEBUG(3,("request_oplock_break: broke oplock.\n"));
2980 return True;
2983 /****************************************************************************
2984 check if a snum is in use
2985 ****************************************************************************/
2986 BOOL snum_used(int snum)
2988 int i;
2989 for (i=0;i<MAX_CONNECTIONS;i++)
2990 if (OPEN_CNUM(i) && (SNUM(i) == snum))
2991 return(True);
2992 return(False);
2995 /****************************************************************************
2996 reload the services file
2997 **************************************************************************/
2998 BOOL reload_services(BOOL test)
3000 BOOL ret;
3002 if (lp_loaded())
3004 pstring fname;
3005 pstrcpy(fname,lp_configfile());
3006 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
3008 pstrcpy(servicesf,fname);
3009 test = False;
3013 reopen_logs();
3015 if (test && !lp_file_list_changed())
3016 return(True);
3018 lp_killunused(snum_used);
3020 ret = lp_load(servicesf,False);
3022 /* perhaps the config filename is now set */
3023 if (!test)
3024 reload_services(True);
3026 reopen_logs();
3028 load_interfaces();
3031 extern int Client;
3032 if (Client != -1) {
3033 set_socket_options(Client,"SO_KEEPALIVE");
3034 set_socket_options(Client,user_socket_options);
3038 create_mangled_stack(lp_mangledstack());
3040 /* this forces service parameters to be flushed */
3041 become_service(-1,True);
3043 return(ret);
3048 /****************************************************************************
3049 this prevents zombie child processes
3050 ****************************************************************************/
3051 static int sig_hup()
3053 BlockSignals(True,SIGHUP);
3054 DEBUG(0,("Got SIGHUP\n"));
3055 reload_services(False);
3056 #ifndef DONT_REINSTALL_SIG
3057 signal(SIGHUP,SIGNAL_CAST sig_hup);
3058 #endif
3059 BlockSignals(False,SIGHUP);
3060 return(0);
3063 /****************************************************************************
3064 Setup the groups a user belongs to.
3065 ****************************************************************************/
3066 int setup_groups(char *user, int uid, int gid, int *p_ngroups,
3067 int **p_igroups, gid_t **p_groups,
3068 int **p_attrs)
3070 if (-1 == initgroups(user,gid))
3072 if (getuid() == 0)
3074 DEBUG(0,("Unable to initgroups!\n"));
3075 if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000)
3076 DEBUG(0,("This is probably a problem with the account %s\n",user));
3079 else
3081 int i,ngroups;
3082 int *igroups;
3083 int *attrs;
3084 gid_t grp = 0;
3085 ngroups = getgroups(0,&grp);
3086 if (ngroups <= 0)
3087 ngroups = 32;
3088 igroups = (int *)malloc(sizeof(int)*ngroups);
3089 attrs = (int *)malloc(sizeof(int)*ngroups);
3090 for (i=0;i<ngroups;i++)
3092 attrs [i] = 0x7; /* XXXX don't know what NT user attributes are yet! */
3093 igroups[i] = 0x42424242;
3095 ngroups = getgroups(ngroups,(gid_t *)igroups);
3097 if (igroups[0] == 0x42424242)
3098 ngroups = 0;
3100 *p_ngroups = ngroups;
3101 *p_attrs = attrs;
3103 /* The following bit of code is very strange. It is due to the
3104 fact that some OSes use int* and some use gid_t* for
3105 getgroups, and some (like SunOS) use both, one in prototypes,
3106 and one in man pages and the actual code. Thus we detect it
3107 dynamically using some very ugly code */
3108 if (ngroups > 0)
3110 /* does getgroups return ints or gid_t ?? */
3111 static BOOL groups_use_ints = True;
3113 if (groups_use_ints &&
3114 ngroups == 1 &&
3115 SVAL(igroups,2) == 0x4242)
3116 groups_use_ints = False;
3118 for (i=0;groups_use_ints && i<ngroups;i++)
3119 if (igroups[i] == 0x42424242)
3120 groups_use_ints = False;
3122 if (groups_use_ints)
3124 *p_igroups = igroups;
3125 *p_groups = (gid_t *)igroups;
3127 else
3129 gid_t *groups = (gid_t *)igroups;
3130 igroups = (int *)malloc(sizeof(int)*ngroups);
3131 for (i=0;i<ngroups;i++)
3133 igroups[i] = groups[i];
3135 *p_igroups = igroups;
3136 *p_groups = (gid_t *)groups;
3139 DEBUG(3,("%s is in %d groups\n",user,ngroups));
3140 for (i=0;i<ngroups;i++)
3141 DEBUG(3,("%d ",igroups[i]));
3142 DEBUG(3,("\n"));
3144 return 0;
3147 /****************************************************************************
3148 make a connection to a service
3149 ****************************************************************************/
3150 int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid)
3152 int cnum;
3153 int snum;
3154 struct passwd *pass = NULL;
3155 connection_struct *pcon;
3156 BOOL guest = False;
3157 BOOL force = False;
3158 static BOOL first_connection = True;
3160 strlower(service);
3162 snum = find_service(service);
3163 if (snum < 0)
3165 if (strequal(service,"IPC$"))
3167 DEBUG(3,("%s refusing IPC connection\n",timestring()));
3168 return(-3);
3171 DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
3172 return(-2);
3175 if (strequal(service,HOMES_NAME))
3177 if (*user && Get_Pwnam(user,True))
3178 return(make_connection(user,user,password,pwlen,dev,vuid));
3180 if (validated_username(vuid))
3182 strcpy(user,validated_username(vuid));
3183 return(make_connection(user,user,password,pwlen,dev,vuid));
3187 if (!lp_snum_ok(snum) || !check_access(snum)) {
3188 return(-4);
3191 /* you can only connect to the IPC$ service as an ipc device */
3192 if (strequal(service,"IPC$"))
3193 strcpy(dev,"IPC");
3195 if (*dev == '?' || !*dev)
3197 if (lp_print_ok(snum))
3198 strcpy(dev,"LPT1:");
3199 else
3200 strcpy(dev,"A:");
3203 /* if the request is as a printer and you can't print then refuse */
3204 strupper(dev);
3205 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
3206 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
3207 return(-6);
3210 /* lowercase the user name */
3211 strlower(user);
3213 /* add it as a possible user name */
3214 add_session_user(service);
3216 /* shall we let them in? */
3217 if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid))
3219 DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
3220 return(-1);
3223 cnum = find_free_connection(str_checksum(service) + str_checksum(user));
3224 if (cnum < 0)
3226 DEBUG(0,("%s couldn't find free connection\n",timestring()));
3227 return(-1);
3230 pcon = &Connections[cnum];
3231 bzero((char *)pcon,sizeof(*pcon));
3233 /* find out some info about the user */
3234 pass = Get_Pwnam(user,True);
3236 if (pass == NULL)
3238 DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
3239 return(-7);
3242 pcon->read_only = lp_readonly(snum);
3245 pstring list;
3246 StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);
3247 string_sub(list,"%S",service);
3249 if (user_in_list(user,list))
3250 pcon->read_only = True;
3252 StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1);
3253 string_sub(list,"%S",service);
3255 if (user_in_list(user,list))
3256 pcon->read_only = False;
3259 /* admin user check */
3261 /* JRA - original code denied admin user if the share was
3262 marked read_only. Changed as I don't think this is needed,
3263 but old code left in case there is a problem here.
3265 if (user_in_list(user,lp_admin_users(snum))
3266 #if 0
3267 && !pcon->read_only)
3268 #else
3270 #endif
3272 pcon->admin_user = True;
3273 DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
3275 else
3276 pcon->admin_user = False;
3278 pcon->force_user = force;
3279 pcon->vuid = vuid;
3280 pcon->uid = pass->pw_uid;
3281 pcon->gid = pass->pw_gid;
3282 pcon->num_files_open = 0;
3283 pcon->lastused = time(NULL);
3284 pcon->service = snum;
3285 pcon->used = True;
3286 pcon->printer = (strncmp(dev,"LPT",3) == 0);
3287 pcon->ipc = (strncmp(dev,"IPC",3) == 0);
3288 pcon->dirptr = NULL;
3289 pcon->veto_list = NULL;
3290 pcon->hide_list = NULL;
3291 string_set(&pcon->dirpath,"");
3292 string_set(&pcon->user,user);
3294 #if HAVE_GETGRNAM
3295 if (*lp_force_group(snum))
3297 struct group *gptr;
3298 pstring gname;
3300 StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1);
3301 /* default service may be a group name */
3302 string_sub(gname,"%S",service);
3303 gptr = (struct group *)getgrnam(gname);
3305 if (gptr)
3307 pcon->gid = gptr->gr_gid;
3308 DEBUG(3,("Forced group %s\n",gname));
3310 else
3311 DEBUG(1,("Couldn't find group %s\n",gname));
3313 #endif
3315 if (*lp_force_user(snum))
3317 struct passwd *pass2;
3318 fstring fuser;
3319 fstrcpy(fuser,lp_force_user(snum));
3320 pass2 = (struct passwd *)Get_Pwnam(fuser,True);
3321 if (pass2)
3323 pcon->uid = pass2->pw_uid;
3324 string_set(&pcon->user,fuser);
3325 fstrcpy(user,fuser);
3326 pcon->force_user = True;
3327 DEBUG(3,("Forced user %s\n",fuser));
3329 else
3330 DEBUG(1,("Couldn't find user %s\n",fuser));
3334 pstring s;
3335 pstrcpy(s,lp_pathname(snum));
3336 standard_sub(cnum,s);
3337 string_set(&pcon->connectpath,s);
3338 DEBUG(3,("Connect path is %s\n",s));
3341 /* groups stuff added by ih */
3342 pcon->ngroups = 0;
3343 pcon->igroups = NULL;
3344 pcon->groups = NULL;
3345 pcon->attrs = NULL;
3347 if (!IS_IPC(cnum))
3349 /* Find all the groups this uid is in and store them. Used by become_user() */
3350 setup_groups(pcon->user,pcon->uid,pcon->gid,
3351 &pcon->ngroups,&pcon->igroups,&pcon->groups,&pcon->attrs);
3353 /* check number of connections */
3354 if (!claim_connection(cnum,
3355 lp_servicename(SNUM(cnum)),
3356 lp_max_connections(SNUM(cnum)),False))
3358 DEBUG(1,("too many connections - rejected\n"));
3359 return(-8);
3362 if (lp_status(SNUM(cnum)))
3363 claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection);
3365 first_connection = False;
3366 } /* IS_IPC */
3368 pcon->open = True;
3370 /* execute any "root preexec = " line */
3371 if (*lp_rootpreexec(SNUM(cnum)))
3373 pstring cmd;
3374 pstrcpy(cmd,lp_rootpreexec(SNUM(cnum)));
3375 standard_sub(cnum,cmd);
3376 DEBUG(5,("cmd=%s\n",cmd));
3377 smbrun(cmd,NULL,False);
3380 if (!become_user(cnum,pcon->vuid))
3382 DEBUG(0,("Can't become connected user!\n"));
3383 pcon->open = False;
3384 if (!IS_IPC(cnum)) {
3385 yield_connection(cnum,
3386 lp_servicename(SNUM(cnum)),
3387 lp_max_connections(SNUM(cnum)));
3388 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
3390 return(-1);
3393 if (ChDir(pcon->connectpath) != 0)
3395 DEBUG(0,("Can't change directory to %s (%s)\n",
3396 pcon->connectpath,strerror(errno)));
3397 pcon->open = False;
3398 unbecome_user();
3399 if (!IS_IPC(cnum)) {
3400 yield_connection(cnum,
3401 lp_servicename(SNUM(cnum)),
3402 lp_max_connections(SNUM(cnum)));
3403 if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS);
3405 return(-5);
3408 string_set(&pcon->origpath,pcon->connectpath);
3410 #if SOFTLINK_OPTIMISATION
3411 /* resolve any soft links early */
3413 pstring s;
3414 pstrcpy(s,pcon->connectpath);
3415 GetWd(s);
3416 string_set(&pcon->connectpath,s);
3417 ChDir(pcon->connectpath);
3419 #endif
3421 num_connections_open++;
3422 add_session_user(user);
3424 /* execute any "preexec = " line */
3425 if (*lp_preexec(SNUM(cnum)))
3427 pstring cmd;
3428 pstrcpy(cmd,lp_preexec(SNUM(cnum)));
3429 standard_sub(cnum,cmd);
3430 smbrun(cmd,NULL,False);
3433 /* we've finished with the sensitive stuff */
3434 unbecome_user();
3436 /* Add veto/hide lists */
3437 if (!IS_IPC(cnum) && !IS_PRINT(cnum))
3439 set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum)));
3440 set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum)));
3444 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n",
3445 timestring(),
3446 remote_machine,
3447 client_addr(),
3448 lp_servicename(SNUM(cnum)),user,
3449 pcon->uid,
3450 pcon->gid,
3451 (int)getpid()));
3454 return(cnum);
3458 /****************************************************************************
3459 find first available file slot
3460 ****************************************************************************/
3461 int find_free_file(void )
3463 int i;
3464 /* we start at 1 here for an obscure reason I can't now remember,
3465 but I think is important :-) */
3466 for (i=1;i<MAX_OPEN_FILES;i++)
3467 if (!Files[i].open)
3468 return(i);
3469 DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
3470 return(-1);
3473 /****************************************************************************
3474 find first available connection slot, starting from a random position.
3475 The randomisation stops problems with the server dieing and clients
3476 thinking the server is still available.
3477 ****************************************************************************/
3478 static int find_free_connection(int hash )
3480 int i;
3481 BOOL used=False;
3482 hash = (hash % (MAX_CONNECTIONS-2))+1;
3484 again:
3486 for (i=hash+1;i!=hash;)
3488 if (!Connections[i].open && Connections[i].used == used)
3490 DEBUG(3,("found free connection number %d\n",i));
3491 return(i);
3493 i++;
3494 if (i == MAX_CONNECTIONS)
3495 i = 1;
3498 if (!used)
3500 used = !used;
3501 goto again;
3504 DEBUG(1,("ERROR! Out of connection structures\n"));
3505 return(-1);
3509 /****************************************************************************
3510 reply for the core protocol
3511 ****************************************************************************/
3512 int reply_corep(char *outbuf)
3514 int outsize = set_message(outbuf,1,0,True);
3516 Protocol = PROTOCOL_CORE;
3518 return outsize;
3522 /****************************************************************************
3523 reply for the coreplus protocol
3524 ****************************************************************************/
3525 int reply_coreplus(char *outbuf)
3527 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
3528 int outsize = set_message(outbuf,13,0,True);
3529 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
3530 readbraw and writebraw (possibly) */
3531 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
3532 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
3534 Protocol = PROTOCOL_COREPLUS;
3536 return outsize;
3540 /****************************************************************************
3541 reply for the lanman 1.0 protocol
3542 ****************************************************************************/
3543 int reply_lanman1(char *outbuf)
3545 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
3546 int secword=0;
3547 BOOL doencrypt = SMBENCRYPT();
3548 time_t t = time(NULL);
3549 /* We need to save and restore this as it can be destroyed
3550 if we call another server if security=server
3551 Thanks to Paul Nelson @ Thursby for pointing this out.
3553 uint16 mid = SVAL(outbuf, smb_mid);
3555 if (lp_security()>=SEC_USER) secword |= 1;
3556 if (doencrypt) secword |= 2;
3558 set_message(outbuf,13,doencrypt?8:0,True);
3559 SSVAL(outbuf,smb_vwv1,secword);
3560 /* Create a token value and add it to the outgoing packet. */
3561 if (doencrypt)
3562 generate_next_challenge(smb_buf(outbuf));
3564 Protocol = PROTOCOL_LANMAN1;
3566 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
3567 SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
3568 SSVAL(outbuf,smb_vwv2,max_recv);
3569 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
3570 SSVAL(outbuf,smb_vwv4,1);
3571 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
3572 readbraw writebraw (possibly) */
3573 SIVAL(outbuf,smb_vwv6,getpid());
3574 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
3576 put_dos_date(outbuf,smb_vwv8,t);
3578 return (smb_len(outbuf)+4);
3582 /****************************************************************************
3583 reply for the lanman 2.0 protocol
3584 ****************************************************************************/
3585 int reply_lanman2(char *outbuf)
3587 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
3588 int secword=0;
3589 BOOL doencrypt = SMBENCRYPT();
3590 time_t t = time(NULL);
3591 struct cli_state *cli = NULL;
3592 char cryptkey[8];
3593 char crypt_len = 0;
3595 if (lp_security() == SEC_SERVER) {
3596 cli = server_cryptkey();
3599 if (cli) {
3600 DEBUG(3,("using password server validation\n"));
3601 doencrypt = ((cli->sec_mode & 2) != 0);
3604 if (lp_security()>=SEC_USER) secword |= 1;
3605 if (doencrypt) secword |= 2;
3607 if (doencrypt) {
3608 crypt_len = 8;
3609 if (!cli) {
3610 generate_next_challenge(cryptkey);
3611 } else {
3612 memcpy(cryptkey, cli->cryptkey, 8);
3613 set_challenge(cli->cryptkey);
3617 set_message(outbuf,13,crypt_len,True);
3618 SSVAL(outbuf,smb_vwv1,secword);
3619 if (doencrypt)
3620 memcpy(smb_buf(outbuf), cryptkey, 8);
3622 SIVAL(outbuf,smb_vwv6,getpid());
3624 Protocol = PROTOCOL_LANMAN2;
3626 CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
3627 SSVAL(outbuf,smb_vwv2,max_recv);
3628 SSVAL(outbuf,smb_vwv3,lp_maxmux());
3629 SSVAL(outbuf,smb_vwv4,1);
3630 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
3631 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
3632 put_dos_date(outbuf,smb_vwv8,t);
3634 return (smb_len(outbuf)+4);
3638 /****************************************************************************
3639 reply for the nt protocol
3640 ****************************************************************************/
3641 int reply_nt1(char *outbuf)
3643 /* dual names + lock_and_read + nt SMBs + remote API calls */
3644 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
3646 other valid capabilities which we may support at some time...
3647 CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
3648 CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
3651 int secword=0;
3652 BOOL doencrypt = SMBENCRYPT();
3653 time_t t = time(NULL);
3654 int data_len;
3655 struct cli_state *cli = NULL;
3656 char cryptkey[8];
3657 char crypt_len = 0;
3659 if (lp_security() == SEC_SERVER) {
3660 cli = server_cryptkey();
3663 if (cli) {
3664 DEBUG(3,("using password server validation\n"));
3665 doencrypt = ((cli->sec_mode & 2) != 0);
3668 if (doencrypt) {
3669 crypt_len = 8;
3670 if (!cli) {
3671 generate_next_challenge(cryptkey);
3672 } else {
3673 memcpy(cryptkey, cli->cryptkey, 8);
3674 set_challenge(cli->cryptkey);
3678 if (lp_readraw() && lp_writeraw()) {
3679 capabilities |= CAP_RAW_MODE;
3682 if (lp_security() >= SEC_USER) secword |= 1;
3683 if (doencrypt) secword |= 2;
3685 /* decide where (if) to put the encryption challenge, and
3686 follow it with the OEM'd domain name
3688 data_len = crypt_len + strlen(myworkgroup) + 1;
3690 set_message(outbuf,17,data_len,True);
3691 strcpy(smb_buf(outbuf)+crypt_len, myworkgroup);
3693 CVAL(outbuf,smb_vwv1) = secword;
3694 SSVALS(outbuf,smb_vwv16+1,crypt_len);
3695 if (doencrypt)
3696 memcpy(smb_buf(outbuf), cryptkey, 8);
3698 Protocol = PROTOCOL_NT1;
3700 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
3701 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
3702 SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
3703 SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
3704 SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
3705 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
3706 put_long_date(outbuf+smb_vwv11+1,t);
3707 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
3708 SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
3710 return (smb_len(outbuf)+4);
3713 /* these are the protocol lists used for auto architecture detection:
3715 WinNT 3.51:
3716 protocol [PC NETWORK PROGRAM 1.0]
3717 protocol [XENIX CORE]
3718 protocol [MICROSOFT NETWORKS 1.03]
3719 protocol [LANMAN1.0]
3720 protocol [Windows for Workgroups 3.1a]
3721 protocol [LM1.2X002]
3722 protocol [LANMAN2.1]
3723 protocol [NT LM 0.12]
3725 Win95:
3726 protocol [PC NETWORK PROGRAM 1.0]
3727 protocol [XENIX CORE]
3728 protocol [MICROSOFT NETWORKS 1.03]
3729 protocol [LANMAN1.0]
3730 protocol [Windows for Workgroups 3.1a]
3731 protocol [LM1.2X002]
3732 protocol [LANMAN2.1]
3733 protocol [NT LM 0.12]
3735 OS/2:
3736 protocol [PC NETWORK PROGRAM 1.0]
3737 protocol [XENIX CORE]
3738 protocol [LANMAN1.0]
3739 protocol [LM1.2X002]
3740 protocol [LANMAN2.1]
3744 * Modified to recognize the architecture of the remote machine better.
3746 * This appears to be the matrix of which protocol is used by which
3747 * MS product.
3748 Protocol WfWg Win95 WinNT OS/2
3749 PC NETWORK PROGRAM 1.0 1 1 1 1
3750 XENIX CORE 2 2
3751 MICROSOFT NETWORKS 3.0 2 2
3752 DOS LM1.2X002 3 3
3753 MICROSOFT NETWORKS 1.03 3
3754 DOS LANMAN2.1 4 4
3755 LANMAN1.0 4 3
3756 Windows for Workgroups 3.1a 5 5 5
3757 LM1.2X002 6 4
3758 LANMAN2.1 7 5
3759 NT LM 0.12 6 8
3761 * tim@fsg.com 09/29/95
3764 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
3765 #define ARCH_WIN95 0x2
3766 #define ARCH_OS2 0xC /* Again OS/2 is like NT */
3767 #define ARCH_WINNT 0x8
3768 #define ARCH_SAMBA 0x10
3770 #define ARCH_ALL 0x1F
3772 /* List of supported protocols, most desired first */
3773 struct {
3774 char *proto_name;
3775 char *short_name;
3776 int (*proto_reply_fn)(char *);
3777 int protocol_level;
3778 } supported_protocols[] = {
3779 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
3780 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
3781 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
3782 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
3783 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
3784 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
3785 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
3786 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
3787 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
3788 {NULL,NULL},
3792 /****************************************************************************
3793 reply to a negprot
3794 ****************************************************************************/
3795 static int reply_negprot(char *inbuf,char *outbuf)
3797 int outsize = set_message(outbuf,1,0,True);
3798 int Index=0;
3799 int choice= -1;
3800 int protocol;
3801 char *p;
3802 int bcc = SVAL(smb_buf(inbuf),-2);
3803 int arch = ARCH_ALL;
3805 p = smb_buf(inbuf)+1;
3806 while (p < (smb_buf(inbuf) + bcc))
3808 Index++;
3809 DEBUG(3,("Requested protocol [%s]\n",p));
3810 if (strcsequal(p,"Windows for Workgroups 3.1a"))
3811 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
3812 else if (strcsequal(p,"DOS LM1.2X002"))
3813 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3814 else if (strcsequal(p,"DOS LANMAN2.1"))
3815 arch &= ( ARCH_WFWG | ARCH_WIN95 );
3816 else if (strcsequal(p,"NT LM 0.12"))
3817 arch &= ( ARCH_WIN95 | ARCH_WINNT );
3818 else if (strcsequal(p,"LANMAN2.1"))
3819 arch &= ( ARCH_WINNT | ARCH_OS2 );
3820 else if (strcsequal(p,"LM1.2X002"))
3821 arch &= ( ARCH_WINNT | ARCH_OS2 );
3822 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
3823 arch &= ARCH_WINNT;
3824 else if (strcsequal(p,"XENIX CORE"))
3825 arch &= ( ARCH_WINNT | ARCH_OS2 );
3826 else if (strcsequal(p,"Samba")) {
3827 arch = ARCH_SAMBA;
3828 break;
3831 p += strlen(p) + 2;
3834 switch ( arch ) {
3835 case ARCH_SAMBA:
3836 set_remote_arch(RA_SAMBA);
3837 break;
3838 case ARCH_WFWG:
3839 set_remote_arch(RA_WFWG);
3840 break;
3841 case ARCH_WIN95:
3842 set_remote_arch(RA_WIN95);
3843 break;
3844 case ARCH_WINNT:
3845 set_remote_arch(RA_WINNT);
3846 break;
3847 case ARCH_OS2:
3848 set_remote_arch(RA_OS2);
3849 break;
3850 default:
3851 set_remote_arch(RA_UNKNOWN);
3852 break;
3855 /* possibly reload - change of architecture */
3856 reload_services(True);
3858 /* a special case to stop password server loops */
3859 if (Index == 1 && strequal(remote_machine,myhostname) &&
3860 lp_security()==SEC_SERVER)
3861 exit_server("Password server loop!");
3863 /* Check for protocols, most desirable first */
3864 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
3866 p = smb_buf(inbuf)+1;
3867 Index = 0;
3868 if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
3869 while (p < (smb_buf(inbuf) + bcc))
3871 if (strequal(p,supported_protocols[protocol].proto_name))
3872 choice = Index;
3873 Index++;
3874 p += strlen(p) + 2;
3876 if(choice != -1)
3877 break;
3880 SSVAL(outbuf,smb_vwv0,choice);
3881 if(choice != -1) {
3882 extern fstring remote_proto;
3883 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
3884 reload_services(True);
3885 outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
3886 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
3888 else {
3889 DEBUG(0,("No protocol supported !\n"));
3891 SSVAL(outbuf,smb_vwv0,choice);
3893 DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
3895 return(outsize);
3899 /****************************************************************************
3900 close all open files for a connection
3901 ****************************************************************************/
3902 static void close_open_files(int cnum)
3904 int i;
3905 for (i=0;i<MAX_OPEN_FILES;i++)
3906 if( Files[i].cnum == cnum && Files[i].open) {
3907 close_file(i,False);
3913 /****************************************************************************
3914 close a cnum
3915 ****************************************************************************/
3916 void close_cnum(int cnum, uint16 vuid)
3918 DirCacheFlush(SNUM(cnum));
3920 unbecome_user();
3922 if (!OPEN_CNUM(cnum))
3924 DEBUG(0,("Can't close cnum %d\n",cnum));
3925 return;
3928 DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
3929 timestring(),
3930 remote_machine,client_addr(),
3931 lp_servicename(SNUM(cnum))));
3933 yield_connection(cnum,
3934 lp_servicename(SNUM(cnum)),
3935 lp_max_connections(SNUM(cnum)));
3937 if (lp_status(SNUM(cnum)))
3938 yield_connection(cnum,"STATUS.",MAXSTATUS);
3940 close_open_files(cnum);
3941 dptr_closecnum(cnum);
3943 /* execute any "postexec = " line */
3944 if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
3946 pstring cmd;
3947 strcpy(cmd,lp_postexec(SNUM(cnum)));
3948 standard_sub(cnum,cmd);
3949 smbrun(cmd,NULL,False);
3950 unbecome_user();
3953 unbecome_user();
3954 /* execute any "root postexec = " line */
3955 if (*lp_rootpostexec(SNUM(cnum)))
3957 pstring cmd;
3958 strcpy(cmd,lp_rootpostexec(SNUM(cnum)));
3959 standard_sub(cnum,cmd);
3960 smbrun(cmd,NULL,False);
3963 Connections[cnum].open = False;
3964 num_connections_open--;
3965 if (Connections[cnum].ngroups && Connections[cnum].groups)
3967 if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
3968 free(Connections[cnum].groups);
3969 free(Connections[cnum].igroups);
3970 Connections[cnum].groups = NULL;
3971 Connections[cnum].igroups = NULL;
3972 Connections[cnum].ngroups = 0;
3975 free_namearray(Connections[cnum].veto_list);
3976 free_namearray(Connections[cnum].hide_list);
3978 string_set(&Connections[cnum].user,"");
3979 string_set(&Connections[cnum].dirpath,"");
3980 string_set(&Connections[cnum].connectpath,"");
3984 /****************************************************************************
3985 simple routines to do connection counting
3986 ****************************************************************************/
3987 BOOL yield_connection(int cnum,char *name,int max_connections)
3989 struct connect_record crec;
3990 pstring fname;
3991 FILE *f;
3992 int mypid = getpid();
3993 int i;
3995 DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
3997 if (max_connections <= 0)
3998 return(True);
4000 bzero(&crec,sizeof(crec));
4002 pstrcpy(fname,lp_lockdir());
4003 standard_sub(cnum,fname);
4004 trim_string(fname,"","/");
4006 strcat(fname,"/");
4007 strcat(fname,name);
4008 strcat(fname,".LCK");
4010 f = fopen(fname,"r+");
4011 if (!f)
4013 DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
4014 return(False);
4017 fseek(f,0,SEEK_SET);
4019 /* find a free spot */
4020 for (i=0;i<max_connections;i++)
4022 if (fread(&crec,sizeof(crec),1,f) != 1)
4024 DEBUG(2,("Entry not found in lock file %s\n",fname));
4025 fclose(f);
4026 return(False);
4028 if (crec.pid == mypid && crec.cnum == cnum)
4029 break;
4032 if (crec.pid != mypid || crec.cnum != cnum)
4034 fclose(f);
4035 DEBUG(2,("Entry not found in lock file %s\n",fname));
4036 return(False);
4039 bzero((void *)&crec,sizeof(crec));
4041 /* remove our mark */
4042 if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
4043 fwrite(&crec,sizeof(crec),1,f) != 1)
4045 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
4046 fclose(f);
4047 return(False);
4050 DEBUG(3,("Yield successful\n"));
4052 fclose(f);
4053 return(True);
4057 /****************************************************************************
4058 simple routines to do connection counting
4059 ****************************************************************************/
4060 BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
4062 struct connect_record crec;
4063 pstring fname;
4064 FILE *f;
4065 int snum = SNUM(cnum);
4066 int i,foundi= -1;
4067 int total_recs;
4069 if (max_connections <= 0)
4070 return(True);
4072 DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
4074 pstrcpy(fname,lp_lockdir());
4075 standard_sub(cnum,fname);
4076 trim_string(fname,"","/");
4078 if (!directory_exist(fname,NULL))
4079 mkdir(fname,0755);
4081 strcat(fname,"/");
4082 strcat(fname,name);
4083 strcat(fname,".LCK");
4085 if (!file_exist(fname,NULL))
4087 int oldmask = umask(022);
4088 f = fopen(fname,"w");
4089 if (f) fclose(f);
4090 umask(oldmask);
4093 total_recs = file_size(fname) / sizeof(crec);
4095 f = fopen(fname,"r+");
4097 if (!f)
4099 DEBUG(1,("couldn't open lock file %s\n",fname));
4100 return(False);
4103 /* find a free spot */
4104 for (i=0;i<max_connections;i++)
4107 if (i>=total_recs ||
4108 fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
4109 fread(&crec,sizeof(crec),1,f) != 1)
4111 if (foundi < 0) foundi = i;
4112 break;
4115 if (Clear && crec.pid && !process_exists(crec.pid))
4117 fseek(f,i*sizeof(crec),SEEK_SET);
4118 bzero((void *)&crec,sizeof(crec));
4119 fwrite(&crec,sizeof(crec),1,f);
4120 if (foundi < 0) foundi = i;
4121 continue;
4123 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid)))
4125 foundi=i;
4126 if (!Clear) break;
4130 if (foundi < 0)
4132 DEBUG(3,("no free locks in %s\n",fname));
4133 fclose(f);
4134 return(False);
4137 /* fill in the crec */
4138 bzero((void *)&crec,sizeof(crec));
4139 crec.magic = 0x280267;
4140 crec.pid = getpid();
4141 crec.cnum = cnum;
4142 crec.uid = Connections[cnum].uid;
4143 crec.gid = Connections[cnum].gid;
4144 StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
4145 crec.start = time(NULL);
4147 StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
4148 StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1);
4150 /* make our mark */
4151 if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
4152 fwrite(&crec,sizeof(crec),1,f) != 1)
4154 fclose(f);
4155 return(False);
4158 fclose(f);
4159 return(True);
4162 #if DUMP_CORE
4163 /*******************************************************************
4164 prepare to dump a core file - carefully!
4165 ********************************************************************/
4166 static BOOL dump_core(void)
4168 char *p;
4169 pstring dname;
4170 pstrcpy(dname,debugf);
4171 if ((p=strrchr(dname,'/'))) *p=0;
4172 strcat(dname,"/corefiles");
4173 mkdir(dname,0700);
4174 sys_chown(dname,getuid(),getgid());
4175 chmod(dname,0700);
4176 if (chdir(dname)) return(False);
4177 umask(~(0700));
4179 #ifndef NO_GETRLIMIT
4180 #ifdef RLIMIT_CORE
4182 struct rlimit rlp;
4183 getrlimit(RLIMIT_CORE, &rlp);
4184 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
4185 setrlimit(RLIMIT_CORE, &rlp);
4186 getrlimit(RLIMIT_CORE, &rlp);
4187 DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
4189 #endif
4190 #endif
4193 DEBUG(0,("Dumping core in %s\n",dname));
4194 return(True);
4196 #endif
4198 /****************************************************************************
4199 exit the server
4200 ****************************************************************************/
4201 void exit_server(char *reason)
4203 static int firsttime=1;
4204 int i;
4206 if (!firsttime) exit(0);
4207 firsttime = 0;
4209 unbecome_user();
4210 DEBUG(2,("Closing connections\n"));
4211 for (i=0;i<MAX_CONNECTIONS;i++)
4212 if (Connections[i].open)
4213 close_cnum(i,(uint16)-1);
4214 #ifdef DFS_AUTH
4215 if (dcelogin_atmost_once)
4216 dfs_unlogin();
4217 #endif
4218 if (!reason) {
4219 int oldlevel = DEBUGLEVEL;
4220 DEBUGLEVEL = 10;
4221 DEBUG(0,("Last message was %s\n",smb_fn_name(last_message)));
4222 if (last_inbuf)
4223 show_msg(last_inbuf);
4224 DEBUGLEVEL = oldlevel;
4225 DEBUG(0,("===============================================================\n"));
4226 #if DUMP_CORE
4227 if (dump_core()) return;
4228 #endif
4231 locking_end();
4233 DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
4234 exit(0);
4237 /****************************************************************************
4238 do some standard substitutions in a string
4239 ****************************************************************************/
4240 void standard_sub(int cnum,char *str)
4242 if (VALID_CNUM(cnum)) {
4243 char *p, *s, *home;
4245 for ( s=str ; (p=strchr(s, '%')) != NULL ; s=p ) {
4246 switch (*(p+1)) {
4247 case 'H' : if ((home = get_home_dir(Connections[cnum].user))!=NULL)
4248 string_sub(p,"%H",home);
4249 else
4250 p += 2;
4251 break;
4252 case 'P' : string_sub(p,"%P",Connections[cnum].connectpath); break;
4253 case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break;
4254 case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break;
4255 case 'u' : string_sub(p,"%u",Connections[cnum].user); break;
4256 case '\0' : p++; break; /* don't run off the end of the string */
4257 default : p+=2; break;
4261 standard_sub_basic(str);
4265 These flags determine some of the permissions required to do an operation
4267 Note that I don't set NEED_WRITE on some write operations because they
4268 are used by some brain-dead clients when printing, and I don't want to
4269 force write permissions on print services.
4271 #define AS_USER (1<<0)
4272 #define NEED_WRITE (1<<1)
4273 #define TIME_INIT (1<<2)
4274 #define CAN_IPC (1<<3)
4275 #define AS_GUEST (1<<5)
4279 define a list of possible SMB messages and their corresponding
4280 functions. Any message that has a NULL function is unimplemented -
4281 please feel free to contribute implementations!
4283 struct smb_message_struct
4285 int code;
4286 char *name;
4287 int (*fn)();
4288 int flags;
4289 #if PROFILING
4290 unsigned long time;
4291 #endif
4293 smb_messages[] = {
4295 /* CORE PROTOCOL */
4297 {SMBnegprot,"SMBnegprot",reply_negprot,0},
4298 {SMBtcon,"SMBtcon",reply_tcon,0},
4299 {SMBtdis,"SMBtdis",reply_tdis,0},
4300 {SMBexit,"SMBexit",reply_exit,0},
4301 {SMBioctl,"SMBioctl",reply_ioctl,0},
4302 {SMBecho,"SMBecho",reply_echo,0},
4303 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
4304 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
4305 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
4306 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
4307 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
4308 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
4309 {SMBsearch,"SMBsearch",reply_search,AS_USER},
4310 {SMBopen,"SMBopen",reply_open,AS_USER},
4312 /* note that SMBmknew and SMBcreate are deliberately overloaded */
4313 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
4314 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
4316 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
4317 {SMBread,"SMBread",reply_read,AS_USER},
4318 {SMBwrite,"SMBwrite",reply_write,AS_USER},
4319 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC},
4320 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
4321 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
4322 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
4323 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
4325 /* this is a Pathworks specific call, allowing the
4326 changing of the root path */
4327 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
4329 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
4330 {SMBflush,"SMBflush",reply_flush,AS_USER},
4331 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
4332 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
4333 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
4334 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST},
4335 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
4336 {SMBlock,"SMBlock",reply_lock,AS_USER},
4337 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
4339 /* CORE+ PROTOCOL FOLLOWS */
4341 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
4342 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
4343 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
4344 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
4345 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
4347 /* LANMAN1.0 PROTOCOL FOLLOWS */
4349 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
4350 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
4351 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
4352 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
4353 {SMBwritec,"SMBwritec",NULL,AS_USER},
4354 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
4355 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
4356 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC},
4357 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
4358 {SMBioctls,"SMBioctls",NULL,AS_USER},
4359 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE},
4360 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
4362 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC},
4363 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
4364 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
4365 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
4367 {SMBffirst,"SMBffirst",reply_search,AS_USER},
4368 {SMBfunique,"SMBfunique",reply_search,AS_USER},
4369 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
4371 /* LANMAN2.0 PROTOCOL FOLLOWS */
4372 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
4373 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
4374 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
4375 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
4377 /* messaging routines */
4378 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
4379 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
4380 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
4381 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
4383 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
4385 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
4386 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
4387 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
4388 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
4391 /****************************************************************************
4392 return a string containing the function name of a SMB command
4393 ****************************************************************************/
4394 char *smb_fn_name(int type)
4396 static char *unknown_name = "SMBunknown";
4397 static int num_smb_messages =
4398 sizeof(smb_messages) / sizeof(struct smb_message_struct);
4399 int match;
4401 for (match=0;match<num_smb_messages;match++)
4402 if (smb_messages[match].code == type)
4403 break;
4405 if (match == num_smb_messages)
4406 return(unknown_name);
4408 return(smb_messages[match].name);
4412 /****************************************************************************
4413 do a switch on the message type, and return the response size
4414 ****************************************************************************/
4415 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
4417 static int pid= -1;
4418 int outsize = 0;
4419 static int num_smb_messages =
4420 sizeof(smb_messages) / sizeof(struct smb_message_struct);
4421 int match;
4423 #if PROFILING
4424 struct timeval msg_start_time;
4425 struct timeval msg_end_time;
4426 static unsigned long total_time = 0;
4428 GetTimeOfDay(&msg_start_time);
4429 #endif
4431 if (pid == -1)
4432 pid = getpid();
4434 errno = 0;
4435 last_message = type;
4437 /* make sure this is an SMB packet */
4438 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
4440 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
4441 return(-1);
4444 for (match=0;match<num_smb_messages;match++)
4445 if (smb_messages[match].code == type)
4446 break;
4448 if (match == num_smb_messages)
4450 DEBUG(0,("Unknown message type %d!\n",type));
4451 outsize = reply_unknown(inbuf,outbuf);
4453 else
4455 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid));
4456 if (smb_messages[match].fn)
4458 int cnum = SVAL(inbuf,smb_tid);
4459 int flags = smb_messages[match].flags;
4460 uint16 session_tag = SVAL(inbuf,smb_uid);
4462 /* does this protocol need to be run as root? */
4463 if (!(flags & AS_USER))
4464 unbecome_user();
4466 /* does this protocol need to be run as the connected user? */
4467 if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
4468 if (flags & AS_GUEST)
4469 flags &= ~AS_USER;
4470 else
4471 return(ERROR(ERRSRV,ERRinvnid));
4473 /* this code is to work around a bug is MS client 3 without
4474 introducing a security hole - it needs to be able to do
4475 print queue checks as guest if it isn't logged in properly */
4476 if (flags & AS_USER)
4477 flags &= ~AS_GUEST;
4479 /* does it need write permission? */
4480 if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
4481 return(ERROR(ERRSRV,ERRaccess));
4483 /* ipc services are limited */
4484 if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC))
4485 return(ERROR(ERRSRV,ERRaccess));
4487 /* load service specific parameters */
4488 if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False))
4489 return(ERROR(ERRSRV,ERRaccess));
4491 /* does this protocol need to be run as guest? */
4492 if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1)))
4493 return(ERROR(ERRSRV,ERRaccess));
4495 last_inbuf = inbuf;
4497 outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
4499 else
4501 outsize = reply_unknown(inbuf,outbuf);
4505 #if PROFILING
4506 GetTimeOfDay(&msg_end_time);
4507 if (!(smb_messages[match].flags & TIME_INIT))
4509 smb_messages[match].time = 0;
4510 smb_messages[match].flags |= TIME_INIT;
4513 unsigned long this_time =
4514 (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
4515 (msg_end_time.tv_usec - msg_start_time.tv_usec);
4516 smb_messages[match].time += this_time;
4517 total_time += this_time;
4519 DEBUG(2,("TIME %s %d usecs %g pct\n",
4520 smb_fn_name(type),smb_messages[match].time,
4521 (100.0*smb_messages[match].time) / total_time));
4522 #endif
4524 return(outsize);
4528 /****************************************************************************
4529 construct a chained reply and add it to the already made reply
4530 **************************************************************************/
4531 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
4533 static char *orig_inbuf;
4534 static char *orig_outbuf;
4535 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
4536 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
4537 char *inbuf2, *outbuf2;
4538 int outsize2;
4539 char inbuf_saved[smb_wct];
4540 char outbuf_saved[smb_wct];
4541 extern int chain_size;
4542 int wct = CVAL(outbuf,smb_wct);
4543 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
4545 /* maybe its not chained */
4546 if (smb_com2 == 0xFF) {
4547 CVAL(outbuf,smb_vwv0) = 0xFF;
4548 return outsize;
4551 if (chain_size == 0) {
4552 /* this is the first part of the chain */
4553 orig_inbuf = inbuf;
4554 orig_outbuf = outbuf;
4557 /* we need to tell the client where the next part of the reply will be */
4558 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
4559 CVAL(outbuf,smb_vwv0) = smb_com2;
4561 /* remember how much the caller added to the chain, only counting stuff
4562 after the parameter words */
4563 chain_size += outsize - smb_wct;
4565 /* work out pointers into the original packets. The
4566 headers on these need to be filled in */
4567 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
4568 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
4570 /* remember the original command type */
4571 smb_com1 = CVAL(orig_inbuf,smb_com);
4573 /* save the data which will be overwritten by the new headers */
4574 memcpy(inbuf_saved,inbuf2,smb_wct);
4575 memcpy(outbuf_saved,outbuf2,smb_wct);
4577 /* give the new packet the same header as the last part of the SMB */
4578 memmove(inbuf2,inbuf,smb_wct);
4580 /* create the in buffer */
4581 CVAL(inbuf2,smb_com) = smb_com2;
4583 /* create the out buffer */
4584 bzero(outbuf2,smb_size);
4585 set_message(outbuf2,0,0,True);
4586 CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com);
4588 memcpy(outbuf2+4,inbuf2+4,4);
4589 CVAL(outbuf2,smb_rcls) = SUCCESS;
4590 CVAL(outbuf2,smb_reh) = 0;
4591 CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set
4592 means a reply */
4593 SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */
4594 SSVAL(outbuf2,smb_err,SUCCESS);
4595 SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid));
4596 SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid));
4597 SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid));
4598 SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid));
4600 DEBUG(3,("Chained message\n"));
4601 show_msg(inbuf2);
4603 /* process the request */
4604 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
4605 bufsize-chain_size);
4607 /* copy the new reply and request headers over the old ones, but
4608 preserve the smb_com field */
4609 memmove(orig_outbuf,outbuf2,smb_wct);
4610 CVAL(orig_outbuf,smb_com) = smb_com1;
4612 /* restore the saved data, being careful not to overwrite any
4613 data from the reply header */
4614 memcpy(inbuf2,inbuf_saved,smb_wct);
4616 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
4617 if (ofs < 0) ofs = 0;
4618 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
4621 return outsize2;
4626 /****************************************************************************
4627 construct a reply to the incoming packet
4628 ****************************************************************************/
4629 int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
4631 int type = CVAL(inbuf,smb_com);
4632 int outsize = 0;
4633 int msg_type = CVAL(inbuf,0);
4634 extern int chain_size;
4636 smb_last_time = time(NULL);
4638 chain_size = 0;
4639 chain_fnum = -1;
4641 bzero(outbuf,smb_size);
4643 if (msg_type != 0)
4644 return(reply_special(inbuf,outbuf));
4646 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
4647 set_message(outbuf,0,0,True);
4649 memcpy(outbuf+4,inbuf+4,4);
4650 CVAL(outbuf,smb_rcls) = SUCCESS;
4651 CVAL(outbuf,smb_reh) = 0;
4652 CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
4653 means a reply */
4654 SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */
4655 SSVAL(outbuf,smb_err,SUCCESS);
4656 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
4657 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
4658 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
4659 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
4661 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
4663 outsize += chain_size;
4665 if(outsize > 4)
4666 smb_setlen(outbuf,outsize - 4);
4667 return(outsize);
4670 /****************************************************************************
4671 process commands from the client
4672 ****************************************************************************/
4673 static void process(void)
4675 extern int Client;
4677 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4678 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
4679 if ((InBuffer == NULL) || (OutBuffer == NULL))
4680 return;
4682 InBuffer += SMB_ALIGNMENT;
4683 OutBuffer += SMB_ALIGNMENT;
4685 #if PRIME_NMBD
4686 DEBUG(3,("priming nmbd\n"));
4688 struct in_addr ip;
4689 ip = *interpret_addr2("localhost");
4690 if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1");
4691 *OutBuffer = 0;
4692 send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM);
4694 #endif
4696 while (True)
4698 int deadtime = lp_deadtime()*60;
4699 int counter;
4700 int last_keepalive=0;
4701 int service_load_counter = 0;
4702 BOOL got_smb = False;
4704 if (deadtime <= 0)
4705 deadtime = DEFAULT_SMBD_TIMEOUT;
4707 if (lp_readprediction())
4708 do_read_prediction();
4710 errno = 0;
4712 for (counter=SMBD_SELECT_LOOP;
4713 !receive_message_or_smb(Client,oplock_sock,
4714 InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb);
4715 counter += SMBD_SELECT_LOOP)
4717 int i;
4718 time_t t;
4719 BOOL allidle = True;
4720 extern int keepalive;
4722 if (counter > 365 * 3600) /* big number of seconds. */
4724 counter = 0;
4725 service_load_counter = 0;
4728 if (smb_read_error == READ_EOF)
4730 DEBUG(3,("end of file from client\n"));
4731 return;
4734 if (smb_read_error == READ_ERROR)
4736 DEBUG(3,("receive_smb error (%s) exiting\n",
4737 strerror(errno)));
4738 return;
4741 t = time(NULL);
4743 /* become root again if waiting */
4744 unbecome_user();
4746 /* check for smb.conf reload */
4747 if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
4749 service_load_counter = counter;
4751 /* reload services, if files have changed. */
4752 reload_services(True);
4755 /* automatic timeout if all connections are closed */
4756 if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT)
4758 DEBUG(2,("%s Closing idle connection\n",timestring()));
4759 return;
4762 if (keepalive && (counter-last_keepalive)>keepalive)
4764 struct cli_state *cli = server_client();
4765 if (!send_keepalive(Client)) {
4766 DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
4767 return;
4769 /* also send a keepalive to the password server if its still
4770 connected */
4771 if (cli && cli->initialised)
4772 send_keepalive(cli->fd);
4773 last_keepalive = counter;
4776 /* check for connection timeouts */
4777 for (i=0;i<MAX_CONNECTIONS;i++)
4778 if (Connections[i].open)
4780 /* close dirptrs on connections that are idle */
4781 if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
4782 dptr_idlecnum(i);
4784 if (Connections[i].num_files_open > 0 ||
4785 (t-Connections[i].lastused)<deadtime)
4786 allidle = False;
4789 if (allidle && num_connections_open>0)
4791 DEBUG(2,("%s Closing idle connection 2\n",timestring()));
4792 return;
4796 if(got_smb)
4797 process_smb(InBuffer, OutBuffer);
4798 else
4799 process_local_message(oplock_sock, InBuffer, BUFFER_SIZE);
4804 /****************************************************************************
4805 initialise connect, service and file structs
4806 ****************************************************************************/
4807 static void init_structs(void )
4809 int i;
4810 get_myname(myhostname,NULL);
4812 for (i=0;i<MAX_CONNECTIONS;i++)
4814 Connections[i].open = False;
4815 Connections[i].num_files_open=0;
4816 Connections[i].lastused=0;
4817 Connections[i].used=False;
4818 string_init(&Connections[i].user,"");
4819 string_init(&Connections[i].dirpath,"");
4820 string_init(&Connections[i].connectpath,"");
4821 string_init(&Connections[i].origpath,"");
4824 for (i=0;i<MAX_OPEN_FILES;i++)
4826 Files[i].open = False;
4827 string_init(&Files[i].name,"");
4831 for (i=0;i<MAX_OPEN_FILES;i++)
4833 file_fd_struct *fd_ptr = &FileFd[i];
4834 fd_ptr->ref_count = 0;
4835 fd_ptr->dev = (int32)-1;
4836 fd_ptr->inode = (int32)-1;
4837 fd_ptr->fd = -1;
4838 fd_ptr->fd_readonly = -1;
4839 fd_ptr->fd_writeonly = -1;
4840 fd_ptr->real_open_flags = -1;
4843 init_dptrs();
4846 /****************************************************************************
4847 usage on the program
4848 ****************************************************************************/
4849 static void usage(char *pname)
4851 DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
4853 printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
4854 printf("Version %s\n",VERSION);
4855 printf("\t-D become a daemon\n");
4856 printf("\t-p port listen on the specified port\n");
4857 printf("\t-d debuglevel set the debuglevel\n");
4858 printf("\t-l log basename. Basename for log/debug files\n");
4859 printf("\t-s services file. Filename of services file\n");
4860 printf("\t-P passive only\n");
4861 printf("\t-a overwrite log file, don't append\n");
4862 printf("\n");
4866 /****************************************************************************
4867 main program
4868 ****************************************************************************/
4869 int main(int argc,char *argv[])
4871 extern BOOL append_log;
4872 /* shall I run as a daemon */
4873 BOOL is_daemon = False;
4874 int port = SMB_PORT;
4875 int opt;
4876 extern char *optarg;
4877 char pidFile[100] = { 0 };
4879 #ifdef NEED_AUTH_PARAMETERS
4880 set_auth_parameters(argc,argv);
4881 #endif
4883 #ifdef SecureWare
4884 setluid(0);
4885 #endif
4887 append_log = True;
4889 TimeInit();
4891 strcpy(debugf,SMBLOGFILE);
4893 setup_logging(argv[0],False);
4895 charset_initialise();
4897 /* make absolutely sure we run as root - to handle cases whre people
4898 are crazy enough to have it setuid */
4899 #ifdef USE_SETRES
4900 setresuid(0,0,0);
4901 #else
4902 setuid(0);
4903 seteuid(0);
4904 setuid(0);
4905 seteuid(0);
4906 #endif
4908 fault_setup(exit_server);
4909 signal(SIGTERM , SIGNAL_CAST dflt_sig);
4911 /* we want total control over the permissions on created files,
4912 so set our umask to 0 */
4913 umask(0);
4915 GetWd(OriginalDir);
4917 init_uid();
4919 /* this is for people who can't start the program correctly */
4920 while (argc > 1 && (*argv[1] != '-'))
4922 argv++;
4923 argc--;
4926 while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF)
4927 switch (opt)
4929 case 'f':
4930 strncpy(pidFile, optarg, sizeof(pidFile));
4931 break;
4932 case 'O':
4933 strcpy(user_socket_options,optarg);
4934 break;
4935 case 'i':
4936 strcpy(scope,optarg);
4937 break;
4938 case 'P':
4940 extern BOOL passive;
4941 passive = True;
4943 break;
4944 case 's':
4945 strcpy(servicesf,optarg);
4946 break;
4947 case 'l':
4948 strcpy(debugf,optarg);
4949 break;
4950 case 'a':
4952 extern BOOL append_log;
4953 append_log = !append_log;
4955 break;
4956 case 'D':
4957 is_daemon = True;
4958 break;
4959 case 'd':
4960 if (*optarg == 'A')
4961 DEBUGLEVEL = 10000;
4962 else
4963 DEBUGLEVEL = atoi(optarg);
4964 break;
4965 case 'p':
4966 port = atoi(optarg);
4967 break;
4968 case 'h':
4969 usage(argv[0]);
4970 exit(0);
4971 break;
4972 default:
4973 usage(argv[0]);
4974 exit(1);
4977 reopen_logs();
4979 DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
4980 DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n"));
4982 #ifndef NO_GETRLIMIT
4983 #ifdef RLIMIT_NOFILE
4985 struct rlimit rlp;
4986 getrlimit(RLIMIT_NOFILE, &rlp);
4987 rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES;
4988 setrlimit(RLIMIT_NOFILE, &rlp);
4989 getrlimit(RLIMIT_NOFILE, &rlp);
4990 DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur));
4992 #endif
4993 #endif
4996 DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
4997 getuid(),getgid(),geteuid(),getegid()));
4999 if (sizeof(uint16) < 2 || sizeof(uint32) < 4)
5001 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
5002 exit(1);
5005 init_structs();
5007 if (!reload_services(False))
5008 return(-1);
5010 codepage_initialise(lp_client_code_page());
5012 strcpy(myworkgroup, lp_workgroup());
5014 #ifndef NO_SIGNAL_TEST
5015 signal(SIGHUP,SIGNAL_CAST sig_hup);
5016 #endif
5018 DEBUG(3,("%s loaded services\n",timestring()));
5020 if (!is_daemon && !is_a_socket(0))
5022 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
5023 is_daemon = True;
5026 if (is_daemon)
5028 DEBUG(3,("%s becoming a daemon\n",timestring()));
5029 become_daemon();
5032 if (*pidFile)
5034 int fd;
5035 char buf[20];
5037 if ((fd = open(pidFile,
5038 #ifdef O_NONBLOCK
5039 O_NONBLOCK |
5040 #endif
5041 O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
5043 DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
5044 exit(1);
5046 if(fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
5048 DEBUG(0,("ERROR: smbd is already running\n"));
5049 exit(1);
5051 sprintf(buf, "%u\n", (unsigned int) getpid());
5052 if (write(fd, buf, strlen(buf)) < 0)
5054 DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
5055 exit(1);
5057 /* Leave pid file open & locked for the duration... */
5060 if (!open_sockets(is_daemon,port))
5061 exit(1);
5063 if (!locking_init())
5064 exit(1);
5066 /* possibly reload the services file. */
5067 reload_services(True);
5069 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
5071 if (*lp_rootdir())
5073 if (sys_chroot(lp_rootdir()) == 0)
5074 DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
5077 /* Setup the oplock IPC socket. */
5078 if(!open_oplock_ipc())
5079 exit(1);
5081 process();
5082 close_sockets();
5084 exit_server("normal exit");
5085 return(0);