home *** CD-ROM | disk | FTP | other *** search
- /*
- Unix SMB/Netbios implementation.
- Version 1.8.
- Copyright (C) Andrew Tridgell 1992,1993,1994
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include "includes.h"
- #include "loadparm.h"
- #include "pcap.h"
- #include "trans2.h"
- #include "reply.h"
-
- pstring OriginalDir ="/";
- pstring servicesf = SERVICES;
- extern pstring debugf;
-
- BOOL append_log = True;
-
- char *InBuffer = NULL;
- char *OutBuffer = NULL;
-
- int initial_uid = 0;
- int initial_gid = 0;
-
- /* have I done a become_user? */
- int done_become_user = -1;
-
- /* the last message the was processed */
- int last_message = -1;
-
- /* does getgroups return ints or gid_t ?? */
- BOOL groups_use_ints = True;
-
- /* a useful macro to debug the last message processed */
- #define LAST_MESSAGE() smb_fn_name(last_message)
-
- extern BOOL NeedSwap;
- extern pstring scope;
- extern int DEBUGLEVEL;
- extern char magic_char;
-
- connection_struct Connections[MAX_CONNECTIONS];
- files_struct Files[MAX_OPEN_FILES];
-
- /* local prototype */
- static char *build_print_command(int snum, char *command, char *syscmd, char *filename);
-
- extern int Protocol;
-
- int maxxmit = BUFFER_SIZE;
-
- int chain_size = 0;
-
- /* a fnum to use when chaining */
- int chain_fnum = -1;
-
- /* total number of open files */
- int num_files_open = 0;
-
- /* this structure is used to hold information about the machine that
- the program is running on */
- extern machine_struct machine_info;
-
- /* booleans from smb_flg2 when PROTOCOL >= LANMAN2 */
- BOOL long_filenames = False;
- extern BOOL casesignames;
-
- fstring remote_machine="";
-
-
- /* these can be set by some functions to override the error codes */
- int unix_ERR_class=SUCCESS;
- int unix_ERR_code=0;
-
-
- extern int extra_time_offset;
-
- pstring myhostname="";
- extern struct in_addr myip;
-
-
- /****************************************************************************
- change a dos mode to a unix mode
- ****************************************************************************/
- mode_t unix_mode(int cnum,int dosmode)
- {
- mode_t result = 0444;
-
- if ((dosmode & aRONLY) == 0)
- result |= (S_IWUSR | S_IWGRP | S_IWOTH);
-
- if ((dosmode & aDIR) != 0)
- result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH);
-
- if ((dosmode & aARCH) != 0)
- result |= S_IXUSR;
-
- if (MAP_SYSTEM(cnum) && ((dosmode & aSYSTEM) != 0))
- result |= S_IXGRP;
-
- if (MAP_HIDDEN(cnum) && ((dosmode & aHIDDEN) != 0))
- result |= S_IXOTH;
-
- result &= CREATE_MODE(cnum);
- return(result);
- }
-
-
- /****************************************************************************
- change a unix mode to a dos mode
- ****************************************************************************/
- int dos_mode(int cnum,char *path,struct stat *sbuf)
- {
- int result = 0;
-
- if (!CAN_WRITE(cnum))
- result |= aRONLY;
- else
- if (!((sbuf->st_mode & S_IWOTH) ||
- ((sbuf->st_mode & S_IWUSR) && Connections[cnum].uid == sbuf->st_uid) ||
- ((sbuf->st_mode & S_IWGRP) &&
- in_group(sbuf->st_gid,Connections[cnum].gid,
- Connections[cnum].ngroups,Connections[cnum].igroups))))
- result |= aRONLY;
-
- if ((sbuf->st_mode & S_IXUSR) != 0)
- result |= aARCH;
-
- if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0))
- result |= aSYSTEM;
-
- if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0))
- result |= aHIDDEN;
-
- if (S_ISDIR(sbuf->st_mode))
- result = aDIR;
-
- /* hide files with a name starting with a . */
- if (lp_hide_dot_files(SNUM(cnum)))
- {
- char *p = strrchr(path,'/');
- if (p)
- p++;
- else
- p = path;
-
- if (p[0] == '.' && p[1] != '.' && p[1] != 0)
- result |= aHIDDEN;
- }
-
- return(result);
- }
-
-
- struct dptr_struct
- {
- int key;
- int pid;
- void *ptr;
- BOOL valid;
- BOOL expect_close;
- char *wcard; /* Field only used for lanman2 trans2_findfirst/next searches */
- uint16 attr; /* Field only used for lanman2 trans2_findfirst/next searches */
- pstring path;
- }
- dirptrs[MAXDIR];
-
- BOOL dptrs_init=False;
- int next_key = 1;
-
- /****************************************************************************
- convert a filename to a unix filename from dos
- ****************************************************************************/
- void unix_convert(char *name,int cnum)
- {
- if(long_filenames)
- unix_convert_lanman2(name,HOME(cnum),casesignames);
- else
- unix_convert_83(name,HOME(cnum),lp_manglednames(SNUM(cnum)), lp_mangled_map(SNUM(cnum)));
- }
-
- /****************************************************************************
- check a filename - possibly caling reducename
- ****************************************************************************/
- BOOL check_name(char *name,int cnum)
- {
- BOOL ret;
-
- if (Connections[cnum].printer && strstr(name,"dev/"))
- {
- fstring name2;
- sprintf(name2,"%s.XXXXXX",remote_machine);
- strcpy(name,(char *)mktemp(name2));
- return(True);
- }
-
- ret = reduce_name(name,HOME(cnum),lp_widelinks(SNUM(cnum)));
- if (!ret)
- DEBUG(5,("check_name on %s failed\n",name));
-
- return(ret);
- }
-
- /****************************************************************************
- check a filename - possibly caling reducename
- ****************************************************************************/
- void check_for_pipe(char *fname)
- {
- /* special case of pipe opens */
- char s[10];
- StrnCpy(s,fname,9);
- strlower(s);
- if (strstr(s,"pipe/"))
- {
- DEBUG(3,("Rejecting named pipe open for %s\n",fname));
- unix_ERR_class = ERRSRV;
- unix_ERR_code = ERRaccess;
- }
- }
-
-
- /****************************************************************************
- open a file
- ****************************************************************************/
- void open_file(int fnum,int cnum,char *fname1,int flags,int mode)
- {
- fstring fname;
-
- Files[fnum].open = False;
- Files[fnum].fd = -1;
- errno = EPERM;
-
- strcpy(fname,fname1);
-
- /* check permissions */
- if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer)
- {
- DEBUG(3,("Permission denied opening %s\n",fname));
- check_for_pipe(fname);
- return;
- }
-
- /* new files with no casesignames get created with the default case */
- if (Protocol >= PROTOCOL_LANMAN2 && !casesignames && (flags & O_CREAT) &&
- !file_exist(fname))
- {
- char *p = strrchr(fname,'/');
- if(!p) p = fname;
- if (lp_defaultcase(cnum) == CASE_UPPER)
- strupper(p);
- else
- strlower(p);
- }
-
- Files[fnum].fd = open(fname,flags,mode);
-
- /* Fix for files ending in '.' */
- if((Files[fnum].fd == -1) && (errno == ENOENT) &&
- (strchr(fname,'.')==NULL))
- {
- strcat(fname,".");
- Files[fnum].fd = open(fname,flags,mode);
- }
-
- if (Files[fnum].fd < 0)
- {
- DEBUG(3,("Error opening file %s (%s)\n",fname,strerror(errno)));
- check_for_pipe(fname);
- return;
- }
-
- if (Files[fnum].fd >= 0)
- {
- num_files_open++;
- Files[fnum].pos = -1;
- Files[fnum].open = True;
- Files[fnum].mmap_ptr = NULL;
- Files[fnum].mmap_size = 0;
- Files[fnum].can_lock = True;
- Files[fnum].read_only = (flags == O_RDONLY);
- Files[fnum].print_file = Connections[cnum].printer;
- Files[fnum].cnum = cnum;
- strcpy(Files[fnum].name,fname);
- Files[fnum].wbmpx_ptr = NULL;
-
- /*
- * If the printer is marked as postscript output a leading
- * file identifier to ensure the file is treated as a raw
- * postscript file.
- * This has a similar effect as CtrlD=0 in WIN.INI file.
- * tim@fsg.com 09/06/94
- */
- if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
- !Files[fnum].read_only)
- {
- DEBUG(3,("Writing postscript line\n"));
- write(Files[fnum].fd,"%!\n",3);
- }
- }
-
- #if USE_MMAP
- /* mmap it if read-only */
- if (Files[fnum].read_only)
- {
- Files[fnum].mmap_size = file_size(fname);
- Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
- PROT_READ,MAP_SHARED,Files[fnum].fd,0);
-
- if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
- {
- DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
- Files[fnum].mmap_ptr = NULL;
- }
- }
- #endif
- }
-
- /****************************************************************************
- close a file - possibly invalidating the read prediction
- ****************************************************************************/
- void close_file(int fnum)
- {
- invalidate_read_prediction(Files[fnum].fd);
- Files[fnum].open = False;
- num_files_open--;
- if(Files[fnum].wbmpx_ptr)
- {
- free((char *)Files[fnum].wbmpx_ptr);
- Files[fnum].wbmpx_ptr = NULL;
- }
-
- #if USE_MMAP
- if(Files[fnum].mmap_ptr)
- {
- munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
- Files[fnum].mmap_ptr = NULL;
- }
- #endif
-
- close(Files[fnum].fd);
-
- /* NT uses smbclose to start a print - weird */
- if (Files[fnum].print_file)
- print_file(fnum);
-
- /* check for magic scripts */
- check_magic(fnum,Files[fnum].cnum);
- }
-
- /****************************************************************************
- seek a file. Try to avoid the seek if possible
- ****************************************************************************/
- int seek_file(int fnum,int pos)
- {
- int offset = 0;
- #if 0
- if (Files[fnum].pos == pos)
- return(pos);
- #endif
- if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum))
- offset = 3;
-
- Files[fnum].pos = lseek(Files[fnum].fd,pos+offset,SEEK_SET) - offset;
- return(Files[fnum].pos);
- }
-
- /****************************************************************************
- read from a file
- ****************************************************************************/
- int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact)
- {
- int ret=0;
-
- if (Files[fnum].read_only)
- {
- ret = read_predict(Files[fnum].fd,
- pos,
- data,
- maxcnt);
-
- data += ret;
- maxcnt -= ret;
- mincnt = MAX(mincnt-ret,0);
- pos += ret;
- }
-
- #if USE_MMAP
- if (Files[fnum].mmap_ptr)
- {
- int num = MIN(maxcnt,Files[fnum].mmap_size-pos);
- if (num > 0)
- {
- memcpy(data,Files[fnum].mmap_ptr+pos,num);
- data += num;
- pos += num;
- maxcnt -= num;
- mincnt = MAX(mincnt-num,0);
- ret += num;
- }
- }
- #endif
-
- if (maxcnt <= 0)
- return(ret);
-
- if (seek_file(fnum,pos) != pos)
- {
- DEBUG(3,("Failed to seek to %d\n",pos));
- return(ret);
- }
-
- if (maxcnt > 0)
- ret += read_with_timeout(Files[fnum].fd,
- data,
- mincnt,
- maxcnt,
- timeout,
- exact);
-
- return(ret);
- }
-
-
- /****************************************************************************
- initialise the dir array
- ****************************************************************************/
- void init_dptrs(void)
- {
- int i;
- if (dptrs_init) return;
- for (i=0;i<MAXDIR;i++)
- dirptrs[i].valid = False;
- dptrs_init = True;
- }
-
- /****************************************************************************
- get the dir ptr for a dir index
- ****************************************************************************/
- void *dptr_get(int key)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && dirptrs[i].key == key)
- return(dirptrs[i].ptr);
- return(NULL);
- }
-
- /****************************************************************************
- get the dir path for a dir index
- ****************************************************************************/
- char *dptr_path(int key)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && dirptrs[i].key == key)
- return(dirptrs[i].path);
- return(NULL);
- }
-
- /****************************************************************************
- get the dir wcard for a dir index (lanman2 specific)
- ****************************************************************************/
- char *dptr_wcard(int key)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && dirptrs[i].key == key)
- return(dirptrs[i].wcard);
- return(NULL);
- }
-
- /****************************************************************************
- set the dir wcard for a dir index (lanman2 specific)
- Returns 0 on ok, 1 on fail.
- ****************************************************************************/
- int dptr_set_wcard(int key, char *wcard)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && dirptrs[i].key == key)
- {
- dirptrs[i].wcard = wcard;
- return 0;
- }
- return 1;
- }
-
- /****************************************************************************
- set the dir attrib for a dir index (lanman2 specific)
- Returns 0 on ok, 1 on fail.
- ****************************************************************************/
- int dptr_set_attr(int key, uint16 attr)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && dirptrs[i].key == key)
- {
- dirptrs[i].attr = attr;
- return 0;
- }
- return 1;
- }
-
- /****************************************************************************
- get the dir attrib for a dir index (lanman2 specific)
- ****************************************************************************/
- uint16 dptr_attr(int key)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && dirptrs[i].key == key)
- return(dirptrs[i].attr);
- return(0);
- }
-
-
- /****************************************************************************
- check a key
- ****************************************************************************/
- BOOL key_ok(int key)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && dirptrs[i].key == key)
- return(True);
- return(False);
- }
-
- /****************************************************************************
- prompte a dptr (to make it recently used)
- ****************************************************************************/
- void dptr_promote(int key)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && dirptrs[i].key == key)
- {
- struct dptr_struct d;
- int j;
- d = dirptrs[i];
- for (j=i;j>0;j--)
- dirptrs[j] = dirptrs[j-1];
- dirptrs[0] = d;
- return;
- }
- }
-
-
- /****************************************************************************
- demote a dptr (to make it likely to get closed)
- ****************************************************************************/
- void dptr_demote(int key)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && dirptrs[i].key == key)
- {
- struct dptr_struct d;
- int j;
- d = dirptrs[i];
- for (j=i;j<(MAXDIR-1) && dirptrs[j].valid;j++)
- dirptrs[j] = dirptrs[j+1];
- dirptrs[j] = d;
- return;
- }
- }
-
-
- /****************************************************************************
- find a free key
- ****************************************************************************/
- int find_key(int start)
- {
- int key;
-
- for (key=start;key<256;key++)
- if (!key_ok(key))
- return(key);
-
- for (key=1;key<start;key++)
- if (!key_ok(key))
- return(key);
-
- DEBUG(0,("ERROR: Out of dirptr keys!\n"));
- return 1;
- }
-
-
- /****************************************************************************
- close a dptr
- ****************************************************************************/
- void dptr_close(int key)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && dirptrs[i].key == key)
- {
- if (dirptrs[i].ptr)
- closedir(dirptrs[i].ptr);
- /* Lanman 2 specific code */
- if (dirptrs[i].wcard)
- free(dirptrs[i].wcard);
- dirptrs[i].valid = False;
- next_key = key+1;
- if (next_key > 255) next_key = 1;
- return;
- }
- }
-
- /****************************************************************************
- close a dptr that matches a given path, only if it matches the pid also
- ****************************************************************************/
- void dptr_closepath(char *path,int pid)
- {
- int i;
- for (i=0;i<MAXDIR;i++)
- if (dirptrs[i].valid && pid == dirptrs[i].pid)
- {
- DEBUG(5,("closepath [%s] [%s]\n",path,dirptrs[i].path));
- if (strequal(dirptrs[i].path,path))
- {
- if (dirptrs[i].ptr)
- closedir(dirptrs[i].ptr);
- if (dirptrs[i].wcard)
- free(dirptrs[i].wcard);
- dirptrs[i].valid = False;
- next_key = dirptrs[i].key+1;
- if (next_key > 255) next_key = 1;
- }
- }
- }
-
- /****************************************************************************
- create a new dir ptr
- ****************************************************************************/
- int dptr_create(void *p,char *path, BOOL expect_close,int pid)
- {
- int i,key;
-
- for (i=0;i<MAXDIR;i++)
- if (!dirptrs[i].valid)
- break;
-
- /* as a second option, grab one not marked for expect_close */
- if (i == MAXDIR)
- for (i=MAXDIR-1;i>=0;i--)
- if (!dirptrs[i].expect_close)
- {
- dptr_close(dirptrs[i].key);
- break;
- }
-
- if (i < 0)
- {
- /* All dirptrs are used by uncloseable SMBffirsts */
- DEBUG(0,("Error - all dirptrs in use by SMBffirsts.\n"));
- return(-1);
- }
-
- dirptrs[i].ptr = p;
- strcpy(dirptrs[i].path,path);
- key = find_key(next_key);
- dirptrs[i].key = key;
- dirptrs[i].valid = True;
- dirptrs[i].pid = pid;
- dirptrs[i].expect_close = expect_close;
- dirptrs[i].wcard = NULL; /* Only used in lanman2 searches */
- dirptrs[i].attr = 0; /* Only used in lanman2 searches */
-
- dptr_promote(key);
-
- DEBUG(3,("creating new dirptr %d (0x%x) for path %s, expect_close = %d\n",key,p,path,
- expect_close));
-
- return(key);
- }
-
- /****************************************************************************
- fill the 5 byte server reserved dptr field
- ****************************************************************************/
- BOOL dptr_fill(char *buf,unsigned int key)
- {
- void *p = dptr_get(key);
- int offset;
- if (!p)
- {
- DEBUG(3,("filling null dirptr %d\n",key));
- return(False);
- }
- offset = telldir(p);
- DEBUG(3,("fill on dirptr 0x%x now at %d\n",p,offset));
- buf[0] = key;
- memcpy(buf+1,(char *)&offset,4);
- DEBUG(3,("filled dirptr %d at offset %d\n",key,offset));
- return(True);
- }
-
- /****************************************************************************
- return True is the offset is at zero
- ****************************************************************************/
- BOOL dptr_zero(char *buf)
- {
- int offset;
- memcpy((char *)&offset,buf+1,4);
- return (offset == 0);
- }
-
- /****************************************************************************
- fetch the dir ptr and seek it given the 5 byte server field
- ****************************************************************************/
- void *dptr_fetch(char *buf,int *num)
- {
- unsigned int key = *(unsigned char *)buf;
- void *p = dptr_get(key);
- int offset;
- if (!p)
- {
- DEBUG(3,("fetched null dirptr %d\n",key));
- return(NULL);
- }
- *num = key;
- memcpy((char *)&offset,buf+1,4);
- seekdir(p,offset);
- dptr_promote(key);
- DEBUG(3,("fetching dirptr %d for path %s\n",key,dptr_path(key)));
- return(p);
- }
-
- /****************************************************************************
- fetch the dir ptr and seek it given the lanman2 parameter block
- ****************************************************************************/
- void *dptr_fetch_lanman2(char *params,int dptr_num)
- {
- void *p = dptr_get(dptr_num);
- uint32 resume_key = SVAL(params,6);
- BOOL uses_resume_key = BITSETW(params+10,2);
-
- if (!p)
- {
- DEBUG(3,("fetched null dirptr %d\n",dptr_num));
- return(NULL);
- }
- if(uses_resume_key)
- seekdir(p,resume_key);
- dptr_promote(dptr_num);
- DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
- return(p);
- }
-
- /****************************************************************************
- start a directory listing
- ****************************************************************************/
- BOOL start_dir(int cnum,char *directory)
- {
- DEBUG(5,("start_dir cnum=%d dir=%s\n",cnum,directory));
-
- if (!check_name(directory,cnum))
- return(False);
-
- Connections[cnum].dirptr = (void *)opendir(directory);
-
- StrnCpy(Connections[cnum].dirpath,directory,sizeof(pstring)-1);
-
- return(Connections[cnum].dirptr != NULL);
- }
-
- /****************************************************************************
- get a directory entry
- ****************************************************************************/
- BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend)
- {
- struct DIRECT *dptr;
- BOOL do_mangling;
- BOOL found = False;
- struct stat sbuf;
- pstring path="";
- pstring pathreal="";
- BOOL isrootdir;
- pstring filename="";
- BOOL matched;
- BOOL has_wild = (strchr(mask,'?') || strchr(mask,'*'));
-
- isrootdir = (strequal(Connections[cnum].dirpath,"./") ||
- strequal(Connections[cnum].dirpath,"."));
-
- if (!Connections[cnum].dirptr)
- return(False);
-
- while (!found)
- {
- dptr = readdir(Connections[cnum].dirptr);
-
- DEBUG(3,("readdir on dirptr 0x%x now at offset %d\n",
- Connections[cnum].dirptr,telldir(Connections[cnum].dirptr)));
-
- if (dptr == NULL)
- return(False);
-
-
- #ifdef NEXT2
- DEBUG(3,("name is: %s\n", dptr->d_name));
- if (telldir(Connections[cnum].dirptr)<0) {
- DEBUG(3,("get_dir_entry encountered null - returning false.\n"));
- return(False);
- }
- #endif
-
- matched = False;
-
- do_mangling = ((has_wild || strchr(mask,magic_char)) &&
- lp_manglednames(SNUM(cnum)));
-
- strcpy(filename,dptr->d_name);
-
- if ((strcmp(filename,mask) == 0) ||
- (name_convert(filename,dptr->d_name,do_mangling,lp_mangled_map(SNUM(cnum))) &&
- mask_match(filename,mask,!isrootdir,False,False)))
- {
- strcpy(fname,filename);
- strcpy(path,Connections[cnum].dirpath);
- strcat(path,"/");
- strcpy(pathreal,path);
- strcat(path,fname);
- strcat(pathreal,dptr->d_name);
- if (stat(pathreal,&sbuf) != 0)
- {
- DEBUG(5,("Couldn't stat 1 [%s]\n",path));
- continue;
- }
-
- if (check_descend &&
- !strequal(fname,".") && !strequal(fname,".."))
- continue;
-
- *mode = dos_mode(cnum,pathreal,&sbuf);
-
- if (((*mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
- {
- DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
- continue;
- }
- *size = sbuf.st_size;
- *date = sbuf.st_mtime;
-
- DEBUG(5,("get_dir_entry found %s fname=%s\n",pathreal,fname));
-
- found = True;
- }
- }
-
- return(found);
- }
-
- static int old_umask = 022;
-
- /****************************************************************************
- load parameters specific to a connection/service
- ****************************************************************************/
- void become_service(int cnum)
- {
- static int last_cnum = -1;
- extern int case_sensitivity;
-
- if (!OPEN_CNUM(cnum))
- {
- last_cnum = -1;
- return;
- }
-
- if (cnum == last_cnum)
- return;
-
- case_sensitivity = lp_defaultcase(SNUM(cnum));
- magic_char = lp_magicchar(SNUM(cnum));
-
- if (ChDir(Connections[cnum].connectpath) != 0)
- {
- DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
- Connections[cnum].connectpath,cnum));
- return;
- }
-
- last_cnum = cnum;
- }
-
-
- /****************************************************************************
- become the user of a connection number
- ****************************************************************************/
- BOOL become_user(int cnum)
- {
- if (!OPEN_CNUM(cnum))
- {
- DEBUG(0,("ERROR: Connection %d not open\n",cnum));
- return(False);
- }
-
- if (done_become_user == cnum)
- {
- DEBUG(3,("Skipping become_user - already user\n"));
- return(True);
- }
-
- if (done_become_user != -1)
- unbecome_user();
-
- if (initial_uid == 0)
- {
- #ifdef USE_SETRES
- if (setresgid(-1,Connections[cnum].gid,-1) != 0)
- #else
- if (setgid(Connections[cnum].gid) != 0)
- #endif
- {
- DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n",
- Connections[cnum].gid,getgid(),getegid()));
- return(False);
- }
-
-
- /* groups stuff added by ih/wreu */
- if (Connections[cnum].ngroups > 0)
- if (setgroups(Connections[cnum].ngroups,(GID_TYPE *)Connections[cnum].groups))
- DEBUG(0,("setgroups call failed!\n"));
-
- #ifdef AIX
- {
- /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */
- priv_t priv;
-
- priv.pv_priv[0] = 0;
- priv.pv_priv[1] = 0;
- if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH,
- &priv, sizeof(priv_t)) < 0 ||
- setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)Connections[cnum].uid) < 0 ||
- seteuid((uid_t)Connections[cnum].uid) < 0)
- DEBUG(1,("Can't set uid (AIX3)"));
- }
- #endif
-
- #ifdef USE_SETRES
- if (setresuid(-1,Connections[cnum].uid,-1) != 0)
- #else
- if ((seteuid(Connections[cnum].uid) != 0) &&
- (setuid(Connections[cnum].uid) != 0))
- #endif
- {
- DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n",
- Connections[cnum].uid,getuid(), geteuid()));
- return(False);
- }
- }
-
- old_umask = umask(0777 & ~lp_create_mode(SNUM(cnum)));
-
- done_become_user = cnum;
-
- if (ChDir(Connections[cnum].connectpath) != 0)
- {
- DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(),
- Connections[cnum].connectpath,cnum));
- unbecome_user();
- return(False);
- }
-
- DEBUG(5,("become_user now uid=(%d,%d) gid=(%d,%d)\n",
- getuid(),geteuid(),getgid(),getegid()));
-
- return(True);
- }
-
- /****************************************************************************
- unbecome the user of a connection number
- ****************************************************************************/
- BOOL unbecome_user(void )
- {
- if (ChDir(OriginalDir) != 0)
- DEBUG(0,("%s chdir(%s) failed\n",timestring(),OriginalDir));
-
- if (done_become_user == -1)
- return(False);
-
- umask(old_umask);
-
- if (initial_uid == 0)
- {
- #ifdef USE_SETRES
- setresuid(-1,getuid(),-1);
- setresgid(-1,getgid(),-1);
- #else
- if (seteuid(initial_uid) != 0)
- setuid(initial_uid);
- setgid(initial_gid);
- #endif
- }
- #ifdef NO_EID
- DEBUG(2,("Running with no EID\n"));
- initial_uid = getuid();
- initial_gid = getgid();
- #else
- if (geteuid() != initial_uid)
- {
- DEBUG(0,("Warning: You appear to have a trapdoor uid system\n"));
- initial_uid = geteuid();
- }
- if (getegid() != initial_gid)
- {
- DEBUG(0,("Warning: You appear to have a trapdoor gid system\n"));
- initial_gid = getegid();
- }
- #endif
-
- if (ChDir(OriginalDir) != 0)
- DEBUG(0,("%s chdir(%s) failed\n",timestring(),OriginalDir));
-
- DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n",
- getuid(),geteuid(),getgid(),getegid()));
-
- done_become_user = -1;
-
- return(True);
- }
-
- /****************************************************************************
- find a service entry
- ****************************************************************************/
- int find_service(char *service)
- {
- int iService;
-
- iService = lp_servicenumber(service);
-
- /* now handle the special case of a home directory */
- if (iService < 0)
- {
- char *phome_dir = get_home_dir(service);
- DEBUG(3,("checking for home directory %s gave %s\n",service,
- phome_dir?phome_dir:"(NULL)"));
- if (phome_dir)
- {
- int iHomeService;
- if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0)
- {
- lp_add_home(service,iHomeService,phome_dir);
- iService = lp_servicenumber(service);
- }
- }
- }
-
- /* If we still don't have a service, attempt to add it as a printer. */
- if (iService < 0)
- {
- int iPrinterService;
-
- if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
- {
- char *pszTemp;
-
- DEBUG(3,("checking whether %s is a valid printer name...\n", service));
- pszTemp = PRINTCAP;
- if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
- {
- DEBUG(3,("%s is a valid printer name\n", service));
- DEBUG(3,("adding %s as a printer service\n", service));
- lp_add_printer(service,iPrinterService);
- iService = lp_servicenumber(service);
- if (iService < 0)
- DEBUG(0,("failed to add %s as a printer service!\n", service));
- }
- else
- DEBUG(3,("%s is not a valid printer name\n", service));
- }
- }
-
- /* just possibly it's a default service? */
- if (iService < 0)
- {
- char *defservice = lp_defaultservice();
- if (defservice && *defservice && !strequal(defservice,service))
- return(find_service(defservice));
- }
-
- if (iService >= 0)
- if (!VALID_SNUM(iService))
- {
- DEBUG(0,("Invalid snum %d for %s\n",iService,service));
- iService = -1;
- }
-
- if (iService < 0)
- DEBUG(3,("find_service() failed to find service %s\n", service));
-
- return (iService);
- }
-
-
- /****************************************************************************
- create an error packet from a cached error.
- ****************************************************************************/
- int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line)
- {
- write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr;
-
- int32 eclass = wbmpx->wr_errclass;
- int32 err = wbmpx->wr_error;
-
- /* We can now delete the auxiliary struct */
- free((char *)wbmpx);
- Files[fnum].wbmpx_ptr = NULL;
- return error_packet(inbuf,outbuf,eclass,err,line);
- }
-
-
- struct
- {
- int unixerror;
- int smbclass;
- int smbcode;
- } unix_smb_errmap[] =
- {
- {EPERM,ERRDOS,ERRnoaccess},
- {EACCES,ERRDOS,ERRnoaccess},
- {ENOENT,ERRDOS,ERRbadfile},
- {EIO,ERRHRD,ERRgeneral},
- {EBADF,ERRSRV,ERRsrverror},
- {EINVAL,ERRSRV,ERRsrverror},
- {EEXIST,ERRDOS,ERRfilexists},
- {ENFILE,ERRDOS,ERRnofids},
- {EMFILE,ERRDOS,ERRnofids},
- {ENOSPC,ERRHRD,ERRdiskfull},
- #ifdef EDQUOT
- {EDQUOT,ERRHRD,ERRdiskfull},
- #endif
- #ifdef ENOTEMPTY
- {ENOTEMPTY,ERRDOS,ERRnoaccess},
- #endif
- {EROFS,ERRHRD,ERRnowrite},
- {0,0,0}
- };
-
-
- /****************************************************************************
- create an error packet from errno
- ****************************************************************************/
- int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line)
- {
- int eclass=def_class;
- int ecode=def_code;
- int i=0;
-
- if (unix_ERR_class != SUCCESS)
- {
- eclass = unix_ERR_class;
- ecode = unix_ERR_code;
- unix_ERR_class = SUCCESS;
- unix_ERR_code = 0;
- }
- else
- {
- while (unix_smb_errmap[i].smbclass != 0)
- {
- if (unix_smb_errmap[i].unixerror == errno)
- {
- eclass = unix_smb_errmap[i].smbclass;
- ecode = unix_smb_errmap[i].smbcode;
- break;
- }
- i++;
- }
- }
-
- return(error_packet(inbuf,outbuf,eclass,ecode,line));
- }
-
-
- /****************************************************************************
- create an error packet. Normally called using the ERROR() macro
- ****************************************************************************/
- int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line)
- {
- int outsize = set_message(outbuf,0,0,True);
- int cmd;
- cmd = CVAL(inbuf,smb_com);
-
- CVAL(outbuf,smb_rcls) = error_class;
- SSVAL(outbuf,smb_err,error_code);
-
- DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n",
- timestring(),
- line,
- (int)CVAL(inbuf,smb_com),
- smb_fn_name(CVAL(inbuf,smb_com)),
- error_class,
- error_code));
-
- if (errno != 0)
- DEBUG(3,("error string = %s\n",strerror(errno)));
-
- return(outsize);
- }
-
-
- /****************************************************************************
- utility function called to see if a file region is locked
- ****************************************************************************/
- BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
- {
- if (count == 0)
- return(False);
-
- if (!lp_locking(SNUM(cnum)))
- return(False);
-
- return(fcntl_lock(Files[fnum].fd,F_GETLK,offset,count,
- (Files[fnum].read_only?F_RDLCK:F_WRLCK)));
- }
-
-
- /****************************************************************************
- utility function called by locking requests
- ****************************************************************************/
- BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
- {
- BOOL ok = False;
-
- if (!lp_locking(SNUM(cnum)))
- return(True);
-
- if (count == 0) {
- *eclass = ERRDOS;
- *ecode = ERRnoaccess;
- return False;
- }
-
- if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
- ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count,
- (Files[fnum].read_only?F_RDLCK:F_WRLCK));
-
- if (!ok) {
- *eclass = ERRDOS;
- *ecode = ERRlock;
- return False;
- }
- return True; /* Got lock */
- }
-
-
- /****************************************************************************
- utility function called by unlocking requests
- ****************************************************************************/
- BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
- {
- BOOL ok = False;
-
- if (!lp_locking(SNUM(cnum)))
- return(True);
-
- if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
- ok = fcntl_lock(Files[fnum].fd,F_SETLK,offset,count,F_UNLCK);
-
- if (!ok) {
- *eclass = ERRDOS;
- *ecode = ERRlock;
- return False;
- }
- return True; /* Did unlock */
- }
-
-
- /****************************************************************************
- open the socket communication
- ****************************************************************************/
- BOOL open_sockets(BOOL is_daemon,int port)
- {
- extern int Client;
- char optval[4];
- int optlen=4;
-
- /* Check if we need to open a new socket by doing
- a harmless socket option on fd 0. If this fails
- we need to create one. */
-
- if (!is_daemon &&
- (getsockopt(0, SOL_SOCKET, SO_TYPE, optval, &optlen)==-1) &&
- (errno == ENOTSOCK))
- {
- DEBUG(0,("standard input is not a socket, will create a socket\n"));
- is_daemon = True;
- }
-
- if (is_daemon)
- {
- int s;
- int sockopt = 1;
- struct sockaddr addr;
- int in_addrlen = sizeof(addr);
-
- /* Stop zombies */
- signal(SIGCLD, SIGNAL_CAST sig_cld);
-
- /* open an incoming socket */
- s = open_socket_in(SOCK_STREAM, port);
- if (s == -1)
- return(False);
-
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(int)))
- {
- DEBUG(0,("Error in setting socket option: %s",strerror(errno)));
- close(s);
- return False;
- }
-
- /* ready to listen */
- if (listen(s, 5) == -1)
- {
- DEBUG(0,("listen: %s",strerror(errno)));
- close(s);
- return False;
- }
-
-
- /* now accept incoming connections - forking a new process
- for each incoming connection */
- DEBUG(2,("waiting for a connection\n"));
- while ((Client = accept(s,&addr,&in_addrlen)))
- {
- if (Client == -1 && errno == EINTR)
- continue;
-
- if (Client == -1)
- {
- DEBUG(0,("accept: %s",strerror(errno)));
- return False;
- }
-
- #ifdef NO_FORK_DEBUG
- /* now set appropriate socket options */
- signal(SIGPIPE, SIGNAL_CAST Abort);
- signal(SIGCLD, SIGNAL_CAST SIG_DFL);
- {
- int one=1;
- setsockopt(Client,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one));
- }
- return True;
- #else
- if (Client != -1 && fork()==0)
- {
- signal(SIGPIPE, SIGNAL_CAST Abort);
- signal(SIGCLD, SIGNAL_CAST SIG_DFL);
-
- /* now set appropriate socket options */
- {
- int one=1;
- setsockopt(Client,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one));
- }
- return True;
- }
- close(Client); /* The parent doesn't need this socket */
- #endif
- }
- close(s);
- return False;
- }
- else
- {
- /* We will abort gracefully when the client or remote system
- goes away */
- signal(SIGPIPE, SIGNAL_CAST Abort);
- Client = 0;
- }
-
- /* now set appropriate socket options */
- {
- int one=1;
- setsockopt(Client,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one));
- #if (defined(TCP_NODELAY) && defined(SOL_TCP))
- setsockopt(Client,SOL_TCP,TCP_NODELAY,(char *)&one,sizeof(one));
- #endif
- }
-
- return True;
- }
-
-
- /****************************************************************************
- this prevents zombie child processes
- ****************************************************************************/
- int sig_cld()
- {
- static int depth = 0;
- if (depth != 0)
- {
- DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n"));
- return(0);
- }
- depth++;
-
- DEBUG(5,("got SIGCLD\n"));
-
- #ifdef USE_WAITPID
- while (waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0);
- #endif
-
- /* Stop zombies */
- /* Stevens, Adv. Unix Prog. says that on system V you must call
- wait before reinstalling the signal handler, because the kernel
- calls the handler from within the signal-call when there is a
- child that has exited. This would lead to an infinite recursion
- if done vice versa. */
-
- signal(SIGCLD, SIGNAL_CAST sig_cld);
-
- #ifndef USE_WAITPID
- while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0);
- #endif
- depth--;
- return 0;
- }
-
-
- /****************************************************************************
- make a connection to a service
- ****************************************************************************/
- int make_connection(char *service,char *user,char *password,char *dev,int vuid)
- {
- int cnum;
- int snum;
- struct passwd *pass = NULL;
- BOOL guest = False;
-
- strlower(service);
-
- snum = find_service(service);
- if (snum < 0)
- {
- if (strequal(service,"IPC$"))
- {
- DEBUG(3,("%s refusing IPC connection\n",timestring()));
- return(-3);
- }
-
- DEBUG(0,("%s couldn't find service %s\n",timestring(),service));
- return(-2);
- }
-
- if (strequal(service,"homes"))
- {
- if (*user && Get_Pwnam(user))
- return(make_connection(user,user,password,dev,vuid));
-
- if (validated_username(vuid))
- {
- strcpy(user,validated_username(vuid));
- return(make_connection(user,user,password,dev,vuid));
- }
- }
-
- if (!check_access(snum))
- return(-1);
-
-
- if (*dev == '?' || !*dev)
- {
- if (strequal(service,"IPC$"))
- strcpy(dev,"IPC");
- else if (lp_print_ok(snum))
- strcpy(dev,"LPT");
- else
- strcpy(dev,"A");
- }
-
- /* if the request is as a printer and you can't print then refuse */
- strupper(dev);
- if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0))
- return(-2);
-
- /* lowercase the user name */
- strlower(user);
-
- /* shall we let them in? */
- if (!authorise_login(snum,user,password,&guest,vuid))
- {
- DEBUG(2,("%s invalid username/password for %s\n",timestring(),service));
- return(-1);
- }
-
- cnum = find_free_connection();
- if (cnum < 0)
- {
- DEBUG(0,("%s couldn't find free connection\n",timestring()));
- return(-1);
- }
-
- /* find out some info about the user */
- pass = Get_Pwnam(user);
-
- if (pass == NULL)
- {
- DEBUG(0,("%s couldn't find account %s\n",timestring(),user));
- return(-1);
- }
-
- Connections[cnum].read_only = lp_readonly(snum);
-
- if (user_in_list(user,lp_readlist(snum)))
- Connections[cnum].read_only = True;
-
- if (user_in_list(user,lp_writelist(snum)))
- Connections[cnum].read_only = False;
-
- Connections[cnum].uid = pass->pw_uid;
- Connections[cnum].gid = pass->pw_gid;
- Connections[cnum].connect_num = cnum;
- Connections[cnum].service = snum;
- Connections[cnum].printer = (strncmp(dev,"LPT",3) == 0);
- Connections[cnum].ipc = (strncmp(dev,"IPC",3) == 0);
- Connections[cnum].dirptr = NULL;
- Connections[cnum].dirpath[0] = 0;
- strcpy(Connections[cnum].connectpath, PATH(snum));
-
- #if HAVE_GETGRNAM
- if (*lp_group(snum))
- {
- struct group *gptr = (struct group *)getgrnam(lp_group(snum));
- if (gptr)
- {
- Connections[cnum].gid = gptr->gr_gid;
- DEBUG(3,("In group %s\n",lp_group(snum)));
- }
- else
- DEBUG(1,("Couldn't find group %s\n",lp_group(snum)));
- }
- #endif
-
- /* groups stuff added by ih */
- Connections[cnum].ngroups = 0;
- Connections[cnum].groups = NULL;
- if (-1 == initgroups(pass->pw_name,Connections[cnum].gid))
- DEBUG(0,("Unable to initgroups!\n")) ;
- else
- {
- int i,ngroups;
- int *igroups;
- GID_TYPE grp = 0;
- ngroups = getgroups(0,&grp);
- if (ngroups <= 0)
- ngroups = 32;
- igroups = (int *)malloc(sizeof(int)*ngroups);
- for (i=0;i<ngroups;i++)
- igroups[i] = 0x42424242;
- ngroups = getgroups(ngroups,(GID_TYPE *)igroups);
-
- if (igroups[0] == 0x42424242)
- ngroups = 0;
-
- Connections[cnum].ngroups = ngroups;
-
- /* The following bit of code is very strange. It is due to the
- fact that some OSes use int* and some use gid_t* for
- getgroups, and some (like SunOS) use both, one in prototypes,
- and one in man pages and the actual code. Thus we detect it
- dynamically using some very ugly code */
- if (ngroups > 0)
- {
- for (i=0;i<ngroups;i++)
- if (igroups[i] == 0x42424242)
- groups_use_ints = False;
-
- if (groups_use_ints)
- {
- Connections[cnum].igroups = igroups;
- Connections[cnum].groups = (gid_t *)igroups;
- }
- else
- {
- gid_t *groups = (gid_t *)igroups;
- igroups = (int *)malloc(sizeof(int)*ngroups);
- for (i=0;i<ngroups;i++)
- igroups[i] = groups[i];
- Connections[cnum].igroups = igroups;
- Connections[cnum].groups = groups;
- }
- }
- DEBUG(3,("%s is in %d groups\n",pass->pw_name,ngroups));
- for (i=0;i<ngroups;i++)
- DEBUG(3,("%d ",igroups[i]));
- DEBUG(3,("\n"));
- }
-
-
- /* check number of connections */
- if (!claim_connection(cnum,
- lp_servicename(SNUM(cnum)),
- lp_max_connections(SNUM(cnum)),False))
- {
- DEBUG(1,("too many connections - rejected\n"));
- return(-4);
- }
-
- if (lp_status(SNUM(cnum)))
- claim_connection(cnum,"STATUS.",100000,True);
-
- Connections[cnum].open = True;
-
- add_session_user(user);
-
- {
- extern struct from_host Client_info;
- DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (pid %d)\n",
- timestring(),
- Client_info.name,Client_info.addr,
- lp_servicename(SNUM(cnum)),user,getpid()));
- }
-
- return(cnum);
- }
-
-
- /****************************************************************************
- find first available file slot
- ****************************************************************************/
- int find_free_file(void )
- {
- int i;
- for (i=1;i<MAX_OPEN_FILES;i++)
- if (!Files[i].open)
- return(i);
- DEBUG(1,("ERROR! Out of file structures\n"));
- return(-1);
- }
-
- /****************************************************************************
- find first available connection slot, starting from a random position.
- The randomisation stops problems with the server dieing and clients
- thinking the server is still available.
- ****************************************************************************/
- int find_free_connection(void )
- {
- int rand_start = (getpid() + (time(NULL)%1000)) % MAX_CONNECTIONS;
- int i;
-
- if (rand_start < 1) rand_start = 1;
-
- for (i=rand_start;i<MAX_CONNECTIONS;i++)
- if (!Connections[i].open)
- {
- DEBUG(3,("found free connection number %d\n",i));
- return(i);
- }
-
- for (i=1;i<rand_start;i++)
- if (!Connections[i].open)
- {
- DEBUG(3,("found free connection number %d\n",i));
- return(i);
- }
-
- DEBUG(1,("ERROR! Out of connection structures\n"));
- return(-1);
- }
-
-
- /* List of supported protocols, most desired first */
- struct {
- char *proto_name;
- int (*proto_reply_fn)(char *);
- int protocol_level;
- } supported_protocols[] = {
- {"NT LANMAN 1.0", reply_nt1 , PROTOCOL_NT1},
- {"LM1.2X002", reply_lanman2 , PROTOCOL_LANMAN2},
- {"DOS LM1.2X002", reply_lanman2 , PROTOCOL_LANMAN2},
- {"LANMAN1.0", reply_lanman1 , PROTOCOL_LANMAN1},
- {"MICROSOFT NETWORKS 3.0", reply_lanman1 , PROTOCOL_LANMAN1},
- {"MICROSOFT NETWORKS 1.03",reply_coreplus,PROTOCOL_COREPLUS},/* core+ protocol */
- {"PC NETWORK PROGRAM 1.0", reply_corep, PROTOCOL_CORE}, /* core protocol */
- {NULL,NULL},
- };
-
-
-
- /****************************************************************************
- reply for the core protocol
- ****************************************************************************/
- int reply_corep(char *outbuf)
- {
- int outsize = set_message(outbuf,1,0,True);
-
- Protocol = PROTOCOL_CORE;
-
- return outsize;
- }
-
-
- /****************************************************************************
- reply for the coreplus protocol
- ****************************************************************************/
- int reply_coreplus(char *outbuf)
- {
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int outsize = set_message(outbuf,13,0,True);
- SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
- readbraw and writebraw (possibly) */
- CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
- #ifdef TESTING
- SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
- #endif
-
- Protocol = PROTOCOL_COREPLUS;
-
- return outsize;
- }
-
-
- /****************************************************************************
- reply for the lanman 1.0 protocol
- ****************************************************************************/
- int reply_lanman1(char *outbuf)
- {
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int outsize = set_message(outbuf,13,0,True);
- CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
- SSVAL(outbuf,smb_vwv1,(lp_security()==SEC_USER)?1:0); /* user level security? don't encrypt */
- SSVAL(outbuf,smb_vwv2,lp_maxxmit());
- SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
- SSVAL(outbuf,smb_vwv4,1);
- SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
- readbraw writebraw (possibly) */
- SIVAL(outbuf,smb_vwv6,getpid());
- SSVAL(outbuf,smb_vwv10, (TimeDiff() / 60) );
-
- put_dos_date(outbuf,smb_vwv8,time(NULL));
-
- Protocol = PROTOCOL_LANMAN1;
-
- return outsize;
- }
-
-
- /****************************************************************************
- reply for the lanman 2.0 protocol
- ****************************************************************************/
- int reply_lanman2(char *outbuf)
- {
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int outsize = set_message(outbuf,13,0,True);
- CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
- SSVAL(outbuf,smb_vwv1,(lp_security()==SEC_USER)?1:0); /* user level security? don't encrypt */
- SSVAL(outbuf,smb_vwv2,lp_maxxmit());
- SSVAL(outbuf,smb_vwv3,lp_maxmux());
- SSVAL(outbuf,smb_vwv4,1);
- SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
- readbraw writebraw (possibly) */
- SIVAL(outbuf,smb_vwv6,getpid());
- SSVAL(outbuf,smb_vwv10, (TimeDiff() / 60) );
-
- put_dos_date(outbuf,smb_vwv8,time(NULL));
-
- Protocol = PROTOCOL_LANMAN2;
-
- return outsize;
- }
-
- /****************************************************************************
- reply for the lanman 2.0 protocol
- ****************************************************************************/
- int reply_nt1(char *outbuf)
- {
- int outsize = set_message(outbuf,15,0,True);
- CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
- SSVAL(outbuf,smb_vwv1,(lp_security()==SEC_USER)?1:0); /* user level security? don't encrypt */
- SSVAL(outbuf,smb_vwv2,lp_maxmux()); /* maxmpx */
- SSVAL(outbuf,smb_vwv3,1); /* num vcs */
- SIVAL(outbuf,smb_vwv4,0xFFFF); /* max buffer */
- SIVAL(outbuf,smb_vwv6,0xFFFF); /* raw size */
- SIVAL(outbuf,smb_vwv8,1); /* session key */
- SIVAL(outbuf,smb_vwv10,0); /* capabilities */
- put_dos_date(outbuf,smb_vwv12,time(NULL));
- SSVAL(outbuf,smb_vwv14, (TimeDiff() / 60) );
-
- Protocol = PROTOCOL_NT1;
-
- return outsize;
- }
-
-
-
- /****************************************************************************
- reply to a negprot
- ****************************************************************************/
- int reply_negprot(char *inbuf,char *outbuf)
- {
- int outsize = set_message(outbuf,1,0,True);
- int index;
- int choice=-1;
- int protocol;
- char *p;
- int bcc = SVAL(smb_buf(inbuf),-2);
-
- /* Check for protocols, most desirable first */
- for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
- {
- p = smb_buf(inbuf)+1;
- index = 0;
- if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
- while (p < (smb_buf(inbuf) + bcc))
- {
- DEBUG(3,("protocol [%s]\n",p));
- if (strequal(p,supported_protocols[protocol].proto_name))
- choice = index;
- index++;
- p += strlen(p) + 2;
- }
- if(choice != -1)
- break;
- }
-
- SSVAL(outbuf,smb_vwv0,choice);
- if(choice != -1)
- {
- outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
- DEBUG(2,("Chose protocol %s\n",supported_protocols[protocol].proto_name));
- }
- else {
- DEBUG(0,("No protocol supported !\n"));
- }
-
- if(Protocol >= PROTOCOL_LANMAN2)
- {
- if (lp_casesignames())
- casesignames = ((CVAL(inbuf,smb_flg) & 0x8) != 0x8);
- long_filenames = ((SVAL(inbuf, smb_flg2) & 0x1) != 0);
- DEBUG(3,("longfilenames=%s casesignames=%s\n",
- BOOLSTR(long_filenames),BOOLSTR(casesignames)));
- }
-
- DEBUG(5,("%s negprot index=%d\n",timestring(),choice));
-
- return(outsize);
- }
-
-
- /****************************************************************************
- parse a connect packet
- ****************************************************************************/
- void parse_connect(char *buf,char *service,char *user,char *password,char *dev)
- {
- char *p = smb_buf(buf) + 1;
- char *p2;
-
- DEBUG(4,("parsing connect string %s\n",p));
-
- p2 = strrchr(p,'\\');
- if (p2 == NULL)
- strcpy(service,p);
- else
- strcpy(service,p2+1);
-
- p += strlen(p) + 2;
-
- strcpy(password,p);
-
- p += strlen(p) + 2;
-
- strcpy(dev,p);
-
- *user = 0;
- p = strchr(service,'%');
- if (p != NULL)
- {
- *p = 0;
- strcpy(user,p+1);
- }
- }
-
-
-
-
-
-
-
- /****************************************************************************
- return number of 1K blocks available on a path and total number
- ****************************************************************************/
- void disk_free(char *path,int *bsize,int *dfree,int *dsize)
- {
- char *df_command = lp_dfree_command();
- #ifdef USE_STATVFS
- struct statvfs fs;
- #else
- #ifdef ULTRIX
- struct fs_data fs;
- #else
- struct statfs fs;
- #endif
- #endif
-
- /* possibly use system() to get the result */
- if (df_command && *df_command)
- {
- int ret;
- pstring syscmd;
- pstring outfile;
-
- sprintf(outfile,"/tmp/dfree.smb.%d",getpid());
- sprintf(syscmd,"%s %s > %s",df_command,path,outfile);
- ret = smbrun(syscmd);
- DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
-
- {
- FILE *f = fopen(outfile,"r");
- *dsize = 0;
- *dfree = 0;
- *bsize = 1024;
- if (f)
- {
- fscanf(f,"%d %d %d",dsize,dfree,bsize);
- fclose(f);
- }
- else
- DEBUG(0,("Can't open %s\n",outfile));
- }
-
- unlink(outfile);
- }
- else
- {
- #ifdef STATFS4
- if (statfs(path,&fs,sizeof(fs),0) != 0)
- #else
- #ifdef USE_STATVFS
- if (statvfs(path, &fs))
- #else
- #ifdef STATFS3
- if (statfs(path,&fs,sizeof(fs)) == -1)
- #else
- if (statfs(path,&fs) == -1)
- #endif /* STATFS3 */
- #endif /* USE_STATVFS */
- #endif /* STATFS4 */
- {
- DEBUG(3,("dfree call failed code errno=%d\n",errno));
- *bsize = 0;
- *dfree = 0;
- *dsize = 0;
- }
- else
- {
- #ifdef ULTRIX
- *bsize = 1024;
- *dfree = fs.fd_req.bfree;
- *dsize = fs.fd_req.btot;
- #else
- #ifdef USE_STATVFS
- *bsize = fs.f_frsize;
- #else
- #ifdef USE_F_FSIZE
- /* eg: osf1 has f_fsize = fundamental filesystem block size,
- f_bsize = optimal transfer block size (MX: 94-04-19) */
- *bsize = fs.f_fsize;
- #else
- /* sun appears to be broken - (noticed by jra@vantive.com) */
- #if defined(SUN) && !defined(sun386) /* Only appears to be wrong for SunOS4.x */
- *bsize = 1024;
- #else
- *bsize = fs.f_bsize;
- #endif
- #endif /* STATFS3 */
- #endif /* USE_STATVFS */
- #ifdef STATFS4
- *dfree = fs.f_bfree;
- #else
- *dfree = fs.f_bavail;
- #endif /* STATFS4 */
- *dsize = fs.f_blocks;
- #endif /* ULTRIX */
- #ifdef SCO
- /* Workaround bug in SCO ODT 2.0 and 3.0.
- * (It returns the filesystem block size in bsize,
- * but returns bfree and blocks in 512-byte units!)
- */
- *bsize = 512;
- #endif
- /* sun appears to be broken - (noticed by jra@vantive.com) */
- #ifdef SUN
- *bsize = 1024;
- #endif
- #ifdef MIPS
- *bsize = 512;
- #endif
- }
- }
-
- /* normalise for DOS usage */
- while (*dfree > WORDMAX || *dsize > WORDMAX)
- {
- *dfree /= 2;
- *dsize /= 2;
- *bsize *= 2;
- if (*bsize > WORDMAX )
- {
- *bsize = WORDMAX;
- if (*dsize > WORDMAX)
- *dsize = WORDMAX;
- if (*dfree > WORDMAX)
- *dfree = WORDMAX;
- break;
- }
- }
- }
-
-
- /****************************************************************************
- print a file - called on closing the file
- ****************************************************************************/
- void print_file(int fnum)
- {
- pstring syscmd="";
- int cnum = Files[fnum].cnum;
- char *tempstr;
-
- tempstr = build_print_command(SNUM(cnum), PRINTCOMMAND(SNUM(cnum)), syscmd, Files[fnum].name);
- if (tempstr != NULL)
- {
- int ret = smbrun(syscmd);
- DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
- }
- else
- DEBUG(0,("Null print command?\n"));
- }
-
-
-
-
-
-
-
-
-
-
-
-
- /****************************************************************************
- run a file if it is a magic script
- ****************************************************************************/
- void check_magic(int fnum,int cnum)
- {
- DEBUG(5,("checking magic for %s\n",Files[fnum].name));
-
- if (!*lp_magicscript(SNUM(cnum)))
- return;
-
- {
- char *p;
- if (!(p = strrchr(Files[fnum].name,'/')))
- p = Files[fnum].name;
- else
- p++;
-
- if (!strequal(lp_magicscript(SNUM(cnum)),p))
- return;
- }
-
- {
- int ret;
- pstring command;
- pstring magic_output;
- pstring fname;
- strcpy(fname,Files[fnum].name);
-
- if (*lp_magicoutput(SNUM(cnum)))
- strcpy(magic_output,lp_magicoutput(SNUM(cnum)));
- else
- sprintf(magic_output,"%s.out",fname);
-
- sprintf(command,"%s %s > %s",
- SHELL_PATH,
- fname,
- magic_output);
-
- ret = smbrun(command);
- DEBUG(3,("Invoking magic command %s gave %d\n",command,ret));
- unlink(fname);
- }
- }
-
-
-
-
- /****************************************************************************
- close all open files for a connection
- ****************************************************************************/
- void close_open_files(int cnum)
- {
- int i;
- for (i=0;i<MAX_OPEN_FILES;i++)
- if( Files[i].cnum == cnum && Files[i].open) {
- close_file(i);
- }
- }
-
-
-
- /****************************************************************************
- close a cnum
- ****************************************************************************/
- void close_cnum(int cnum)
- {
- extern struct from_host Client_info;
-
- unbecome_user();
-
- if (!OPEN_CNUM(cnum))
- {
- DEBUG(0,("Can't close cnum %d\n",cnum));
- return;
- }
-
- DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n",
- timestring(),
- Client_info.name,Client_info.addr,
- lp_servicename(SNUM(cnum))));
-
- yield_connection(cnum,
- lp_servicename(SNUM(cnum)),
- lp_max_connections(SNUM(cnum)));
-
- if (lp_status(SNUM(cnum)))
- yield_connection(cnum,"STATUS.",100000);
-
- close_open_files(cnum);
- Connections[cnum].open = False;
- if (Connections[cnum].ngroups && Connections[cnum].groups)
- {
- if (Connections[cnum].igroups != (int *)Connections[cnum].groups)
- free(Connections[cnum].groups);
- free(Connections[cnum].igroups);
- Connections[cnum].groups = NULL;
- Connections[cnum].igroups = NULL;
- Connections[cnum].ngroups = 0;
- }
- }
-
-
- /****************************************************************************
- simple routines to do connection counting
- ****************************************************************************/
- BOOL yield_connection(int cnum,char *name,int max_connections)
- {
- struct connect_record crec;
- pstring fname;
- FILE *f;
- int mypid = getpid();
- int i;
-
- DEBUG(3,("Yielding connection to %d %s\n",cnum,name));
-
- if (max_connections <= 0)
- return(True);
-
- strcpy(fname,lp_lockdir());
- trim_string(fname,"","/");
-
- strcat(fname,"/");
- strcat(fname,name);
- strcat(fname,".LCK");
-
- f = fopen(fname,"r+");
- if (!f)
- {
- DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
- return(False);
- }
-
- /* find a free spot */
- for (i=0;i<max_connections;i++)
- {
- if (fread(&crec,sizeof(crec),1,f) != 1)
- {
- DEBUG(2,("Entry not found in lock file %s\n",fname));
- fclose(f);
- return(False);
- }
- if (crec.pid == mypid && crec.cnum == cnum)
- break;
- }
-
- if (crec.pid != mypid || crec.cnum != cnum)
- {
- fclose(f);
- DEBUG(2,("Entry not found in lock file %s\n",fname));
- return(False);
- }
-
- memset(&crec,0,sizeof(crec));
-
- /* remove our mark */
- if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 ||
- fwrite(&crec,sizeof(crec),1,f) != 1)
- {
- DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
- fclose(f);
- return(False);
- }
-
- DEBUG(3,("Yield successful\n"));
-
- fclose(f);
- return(True);
- }
-
-
- /****************************************************************************
- simple routines to do connection counting
- ****************************************************************************/
- BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear)
- {
- struct connect_record crec;
- pstring fname;
- FILE *f;
- int snum = SNUM(cnum);
- int i,foundi=-1;
-
- DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
-
- if (max_connections <= 0)
- return(True);
-
- strcpy(fname,lp_lockdir());
- trim_string(fname,"","/");
-
- if (!directory_exist(fname))
- mkdir(fname,0755);
-
- strcat(fname,"/");
- strcat(fname,name);
- strcat(fname,".LCK");
-
- if (!file_exist(fname))
- {
- f = fopen(fname,"w");
- if (f) fclose(f);
- }
-
-
- f = fopen(fname,"r+");
-
- if (!f)
- {
- DEBUG(1,("couldn't open lock file %s\n",fname));
- return(False);
- }
-
- /* find a free spot */
- for (i=0;i<max_connections;i++)
- {
- if (fread(&crec,sizeof(crec),1,f) != 1)
- {
- foundi = i;
- break;
- }
-
- DEBUG(3,("got pid %d at position %d\n",crec.pid,i));
- if (Clear && crec.pid && !process_exists(crec.pid))
- {
- fseek(f,-sizeof(crec),SEEK_CUR);
- memset(&crec,0,sizeof(crec));
- fwrite(&crec,sizeof(crec),1,f);
- if (foundi < 0) foundi = i;
- continue;
- }
- if (foundi >= 0) continue;
- if (foundi < 0 && (crec.pid == 0 || !process_exists(crec.pid)))
- {
- foundi=i;
- if (!Clear) break;
- }
- }
-
- if (foundi < 0)
- {
- DEBUG(3,("no free locks in %s\n",fname));
- fclose(f);
- return(False);
- }
-
- /* fill in the crec */
- memset(&crec,0,sizeof(crec));
- crec.magic = 0x280267;
- crec.pid = getpid();
- crec.cnum = cnum;
- crec.uid = Connections[cnum].uid;
- crec.gid = Connections[cnum].gid;
- StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1);
- crec.start = time(NULL) + GMT_TO_LOCAL*TimeDiff();
- {
- extern struct from_host Client_info;
- StrnCpy(crec.machine,Client_info.name,sizeof(crec.machine)-1);
- StrnCpy(crec.addr,Client_info.addr,sizeof(crec.addr)-1);
- }
-
- /* make our mark */
- if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 ||
- fwrite(&crec,sizeof(crec),1,f) != 1)
- {
- fclose(f);
- return(False);
- }
-
- fclose(f);
- return(True);
- }
-
- /****************************************************************************
- exit the server
- ****************************************************************************/
- void exit_server(void)
- {
- int i;
- DEBUG(3,("%s Server exit\n",timestring()));
- for (i=0;i<MAX_CONNECTIONS;i++)
- if (Connections[i].open)
- close_cnum(i);
- exit(0);
- }
-
- /****************************************************************************
- Build the print command in the supplied buffer. This means getting the
- print command for the service and inserting the printer name and the
- print file name. Return NULL on error, else the passed buffer pointer.
- ****************************************************************************/
- static char *build_print_command(int snum, char *command, char *syscmd, char *filename1)
- {
- char *tstr;
- int iOffset;
- pstring filename;
-
- /* get the print command for the service. */
- tstr = command;
- if (tstr == NULL)
- {
- DEBUG(0,("No print command for service `%s'\n", SERVICE(snum)));
- return (NULL);
- }
-
- /* copy the command into the buffer for extensive meddling. */
- strcpy(syscmd, tstr);
-
- /* look for "%s" in the string. If there is no %s, we cannot print. */
- if (!strstr(syscmd, "%s"))
- {
- DEBUG(0,("No placeholder for the filename in the print command "
- "for service %s!\n", SERVICE(snum)));
- return (NULL);
- }
-
- iOffset = strstr(syscmd, "%s") - syscmd;
-
- /* construct the full path for the filename, shouldn't be necessary unless
- the subshell causes a "cd" to be executed.
- Only use the full path if there isn't a / preceding the %s */
- if (iOffset==0 || syscmd[iOffset-1] != '/')
- {
- strcpy(filename,lp_pathname(snum));
- trim_string(filename,"","/");
- strcat(filename,"/");
- strcat(filename,filename1);
- }
- else
- strcpy(filename,filename1);
-
-
- string_sub(syscmd, "%s", filename);
-
- /* Does the service have a printername? If not, make a fake and empty */
- /* printer name. That way a %p is treated sanely if no printer */
- /* name was specified to replace it. This eventuality is logged. */
- tstr = PRINTERNAME(snum);
- if (tstr == NULL || tstr[0] == '\0')
- {
- DEBUG(3,( "No printer name - using %s.\n", SERVICE(snum)));
- tstr = SERVICE(snum);
- }
-
- string_sub(syscmd, "%p", tstr);
-
- return (syscmd);
- }
-
-
-
- /****************************************************************************
- parse a lpq line
-
- here is an example of lpq output under sunos
-
- Only lines after the Rank get to this routine
-
- Warning: no daemon present
- Rank Owner Job Files Total Size
- 1st tridge 148 README 8096 bytes
- ****************************************************************************/
- BOOL parse_lpq_entry(char *line,print_queue_struct *buf,BOOL first)
- {
- char owner[50]="";
- char fname[50]="";
- int jobid = 0;
- int size = 0;
- pstring dummy;
-
- if (sscanf(line,"%s%s%d%s%d",dummy,owner,&jobid,fname,&size) < 5)
- {
- if (sscanf(line,"%s%s%d (standard input) %d",dummy,owner,&jobid,&size) < 3)
- return(False);
- strcpy(fname,"Stdin");
- }
-
- buf->job = jobid;
- buf->size = size;
- buf->status = first?LPQ_PRINTING:LPQ_QUEUED;
- buf->time = time(NULL) + GMT_TO_LOCAL*TimeDiff();
- StrnCpy(buf->user,owner,sizeof(buf->user)-1);
- StrnCpy(buf->file,fname,sizeof(buf->file)-1);
- return(True);
- }
-
-
-
-
- /****************************************************************************
- get a printer queue
- ****************************************************************************/
- int get_printqueue(int snum,print_queue_struct **queue)
- {
- char *lpq_command = lp_lpqcommand(snum);
- char *printername = PRINTERNAME(snum);
- int ret=0,count=0;
- BOOL foundrank=False;
- pstring syscmd;
- pstring outfile;
- pstring line="";
- FILE *f;
-
- if (!printername || !*printername)
- printername = "lp";
-
- if (!lpq_command || !(*lpq_command))
- {
- DEBUG(5,("No lpq command\n"));
- return(0);
- }
-
- sprintf(outfile,"/tmp/lpq.smb.%d",getpid());
-
- strcpy(syscmd,lpq_command);
- if (!string_sub(syscmd,"%p",printername))
- {
- strcat(syscmd," ");
- strcat(syscmd,printername);
- }
-
- strcat(syscmd," > ");
- strcat(syscmd,outfile);
-
- ret = smbrun(syscmd);
- DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
-
- f = fopen(outfile,"r");
- if (!f)
- return(0);
-
- /* read lines until we get one starting with "Rank" */
- while (!foundrank && !feof(f))
- {
- if (fgets(line,sizeof(pstring),f))
- {
- DEBUG(6,("QUEUE1: %s\n",line));
- if (strncmp(line,"Rank",strlen("Rank")) == 0)
- foundrank = True;
- }
- }
-
- if (foundrank)
- {
- while (fgets(line,sizeof(pstring),f))
- {
- DEBUG(6,("QUEUE2: %s\n",line));
-
- *queue = Realloc(*queue,sizeof(print_queue_struct)*(count+1));
- if (! *queue)
- {
- count = 0;
- break;
- }
-
- /* parse it */
- if (!parse_lpq_entry(line,&(*queue)[count],count==0))
- break;
-
- count++;
- }
- }
- else
- DEBUG(5,("Didn't find keyword Rank\n"));
-
- fclose(f);
- unlink(outfile);
-
- return(count);
- }
-
-
-
-
- /*
- These flags determine some of the permissions required to do an operation
-
- Note that I don't set NEED_WRITE on some write operations because they
- are used by some brain-dead clients when printing, and I don't want to
- force write permissions on print services.
- */
- #define AS_USER (1<<0)
- #define NEED_WRITE (1<<1)
- #define TIME_INIT (1<<2)
-
- /*
- define a list of possible SMB messages and their corresponding
- functions. Any message that has a NULL function is unimplemented -
- please feel free to contribute implementations!
- */
- struct smb_message_struct
- {
- int code;
- char *name;
- int (*fn)();
- int flags;
- #if PROFILING
- unsigned long time;
- #endif
- }
- smb_messages[] = {
-
- /* CORE PROTOCOL */
-
- {SMBnegprot,"SMBnegprot",reply_negprot,0},
- {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
- {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
- {SMBtcon,"SMBtcon",reply_tcon,0},
- {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
- {SMBsearch,"SMBsearch",reply_search,AS_USER},
- {SMBopen,"SMBopen",reply_open,AS_USER},
-
- /* note that SMBmknew and SMBcreate are deliberately overloaded */
- {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
- {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
-
- {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE},
- {SMBread,"SMBread",reply_read,AS_USER},
- {SMBwrite,"SMBwrite",reply_write,AS_USER},
- {SMBclose,"SMBclose",reply_close,AS_USER},
- {SMBtdis,"SMBtdis",reply_tdis,0},
- {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
- {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
- {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
- {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE},
-
- /* this is a Pathworks specific call, allowing the
- changing of the root path */
- {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
-
- {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
- {SMBflush,"SMBflush",reply_flush,AS_USER},
- {SMBctemp,"SMBctemp",reply_ctemp,AS_USER},
- {SMBexit,"SMBexit",reply_exit,0},
- {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER},
- {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
- {SMBsplretq,"SMBsplretq",reply_printqueue,0},
- {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
- {SMBlock,"SMBlock",reply_lock,AS_USER},
- {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
-
- /* CORE+ PROTOCOL FOLLOWS */
-
- {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
- {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
- {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
- {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
- {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
-
- /* LANMAN1.0 PROTOCOL FOLLOWS */
-
- {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
- {SMBreadBs,"SMBreadBs",NULL,AS_USER},
- {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
- {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
- {SMBwritec,"SMBwritec",NULL,AS_USER},
- {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE},
- {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER},
- {SMBtrans,"SMBtrans",reply_trans,AS_USER},
- {SMBtranss,"SMBtranss",NULL,AS_USER},
- {SMBioctl,"SMBioctl",reply_ioctl,0},
- {SMBioctls,"SMBioctls",NULL,AS_USER},
- {SMBcopy,"SMBcopy",NULL,AS_USER},
- {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE},
-
- {SMBecho,"SMBecho",reply_echo,0},
- {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER},
- {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER},
- {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER},
- {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
- {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
- {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER},
-
- {SMBffirst,"SMBffirst",reply_search,AS_USER},
- {SMBfunique,"SMBfunique",reply_search,AS_USER},
- {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
-
- /* LANMAN2.0 PROTOCOL FOLLOWS */
- {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
- {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
- {SMBulogoffX, "SMBulogoffX", NULL, AS_USER}, /* Not implemented (yet) */
- {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER},
- {SMBtranss2, "SMBtranss2", NULL, AS_USER},
-
- /* messaging routines */
- #if 0
- {SMBsends,"SMBsends",test_sends,AS_USER},
- {SMBsendstrt,"SMBsendstrt",string_start,AS_USER},
- {SMBsendend,"SMBsendend",string_stop,AS_USER},
- {SMBsendtxt,"SMBsendtxt",string_text,AS_USER},
- #else
- {SMBsends,"SMBsends",NULL,AS_USER},
- {SMBsendstrt,"SMBsendstrt",NULL,AS_USER},
- {SMBsendend,"SMBsendend",NULL,AS_USER},
- {SMBsendtxt,"SMBsendtxt",NULL,AS_USER},
- #endif
- /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
-
- {SMBsendb,"SMBsendb",NULL,AS_USER},
- {SMBfwdname,"SMBfwdname",NULL,AS_USER},
- {SMBcancelf,"SMBcancelf",NULL,AS_USER},
- {SMBgetmac,"SMBgetmac",NULL,AS_USER}
- };
-
- /****************************************************************************
- return a string containing the function name of a SMB command
- ****************************************************************************/
- char *smb_fn_name(int type)
- {
- static char *unknown_name = "SMBunknown";
- static int num_smb_messages =
- sizeof(smb_messages) / sizeof(struct smb_message_struct);
- int match;
-
- for (match=0;match<num_smb_messages;match++)
- if (smb_messages[match].code == type)
- break;
-
- if (match == num_smb_messages)
- return(unknown_name);
-
- return(smb_messages[match].name);
- }
-
-
- /****************************************************************************
- do a switch on the message type, and return the response size
- ****************************************************************************/
- int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
- {
- int outsize = 0;
- static int num_smb_messages =
- sizeof(smb_messages) / sizeof(struct smb_message_struct);
- int match;
- #if PROFILING
- struct timeval msg_start_time;
- struct timeval msg_end_time;
- static unsigned long total_time = 0;
-
- gettimeofday(&msg_start_time,NULL);
- #endif
-
- errno = 0;
- last_message = type;
-
- for (match=0;match<num_smb_messages;match++)
- if (smb_messages[match].code == type)
- break;
-
- if (match == num_smb_messages)
- {
- DEBUG(0,("Unknown message type %d!\n",type));
- outsize = reply_unknown(inbuf,outbuf);
- }
- else
- {
- DEBUG(3,("switch message %s\n",smb_messages[match].name));
- if (smb_messages[match].fn)
- {
- int cnum = SVAL(inbuf,smb_tid);
- int flags = smb_messages[match].flags;
-
- /* does this protocol need to be run as root? */
- if (!(flags & AS_USER) && (done_become_user != -1))
- unbecome_user();
-
- /* does this protocl need to be run as the connected user? */
- if ((flags & AS_USER) && !become_user(cnum))
- return(ERROR(ERRSRV,ERRinvnid));
-
- /* does it need write permission? */
- if ((flags & NEED_WRITE) && !CAN_WRITE(cnum))
- return(ERROR(ERRSRV,ERRaccess));
-
- /* load service specific parameters */
- become_service(cnum);
-
- outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize);
- }
- else
- outsize = reply_unknown(inbuf,outbuf);
- }
-
- #if PROFILING
- gettimeofday(&msg_end_time,NULL);
- if (!(smb_messages[match].flags & TIME_INIT))
- {
- smb_messages[match].time = 0;
- smb_messages[match].flags |= TIME_INIT;
- }
- {
- unsigned long this_time =
- (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 +
- (msg_end_time.tv_usec - msg_start_time.tv_usec);
- smb_messages[match].time += this_time;
- total_time += this_time;
- }
- DEBUG(2,("TIME %s %d usecs %g pct\n",
- smb_fn_name(type),smb_messages[match].time,
- (100.0*smb_messages[match].time) / total_time));
- #endif
-
- return(outsize);
- }
-
-
- /****************************************************************************
- construct a chained reply and add it to the already made reply
-
- inbuf points to the original message start.
- inbuf2 points to the smb_wct part of the secondary message
- type is the type of the secondary message
- outbuf points to the original outbuffer
- outbuf2 points to the smb_wct field of the new outbuffer
- size is the total length of the incoming message (from inbuf1)
- bufsize is the total buffer size
-
- return how many bytes were added to the response
- ****************************************************************************/
- int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize)
- {
- int outsize = 0;
- char *ibuf,*obuf;
- static int chain_size_in = 0;
- static BOOL in_chain = False;
- static char *last_inbuf=NULL,*last_outbuf=NULL;
- BOOL was_inchain = in_chain;
-
- chain_size += ((int)outbuf2 - (int)outbuf) - smb_wct;
- if (was_inchain)
- {
- inbuf = last_inbuf;
- outbuf = last_outbuf;
- }
- else
- chain_size_in = 0;
-
- in_chain = True;
- last_inbuf = inbuf;
- last_outbuf = outbuf;
-
-
- inbuf2 -= chain_size_in;
-
- chain_size_in += ((int)inbuf2 - (int)inbuf) - smb_wct;
-
-
- /* allocate some space for the in and out buffers of the chained message */
- ibuf = (char *)malloc(size + SAFETY_MARGIN);
- obuf = (char *)malloc(bufsize + SAFETY_MARGIN);
-
- if (!ibuf || !obuf)
- {
- DEBUG(0,("Out of memory in chain reply\n"));
- return(ERROR(ERRSRV,ERRnoresource));
- }
-
- /* create the in buffer */
- memcpy(ibuf,inbuf,smb_wct);
- memcpy(ibuf+smb_wct,inbuf2,size-(int)(inbuf2-inbuf));
- CVAL(ibuf,smb_com) = type;
-
- /* create the out buffer */
- memset(obuf,0,smb_size);
-
- set_message(obuf,0,0,True);
- CVAL(obuf,smb_com) = CVAL(ibuf,smb_com);
-
- memcpy(obuf+4,ibuf+4,4);
- CVAL(obuf,smb_rcls) = SUCCESS;
- CVAL(obuf,smb_reh) = 0;
- CVAL(obuf,smb_flg) = 0x80 | (CVAL(ibuf,smb_flg) & 0x8); /* bit 7 set
- means a reply */
- CVAL(obuf,smb_flg2) = (CVAL(ibuf,smb_flg2) & 1); /* say we support
- long filenames if
- he does */
- SSVAL(obuf,smb_err,SUCCESS);
- SSVAL(obuf,smb_tid,SVAL(inbuf,smb_tid));
- SSVAL(obuf,smb_pid,SVAL(inbuf,smb_pid));
- SSVAL(obuf,smb_uid,SVAL(inbuf,smb_uid));
- SSVAL(obuf,smb_mid,SVAL(inbuf,smb_mid));
-
- /* process the request */
- outsize = switch_message(type,ibuf,obuf,
- (size+smb_wct)-(int)(inbuf2-inbuf),
- bufsize);
-
- /* copy the new reply header over the old one, but preserve
- the smb_com field */
- memcpy(outbuf+smb_com+1,obuf+smb_com+1,smb_wct-(smb_com+1));
-
- /* and copy the data from the reply to the right spot */
- memcpy(outbuf2,obuf+smb_wct,outsize - smb_wct);
-
- /* free the allocated buffers */
- if (ibuf) free(ibuf);
- if (obuf) free(obuf);
-
- in_chain = was_inchain;
-
- /* return how much extra has been added to the packet */
- return(outsize - smb_wct);
- }
-
-
-
- /****************************************************************************
- construct a reply to the incoming packet
- ****************************************************************************/
- int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
- {
- int type = CVAL(inbuf,smb_com);
- int outsize = 0;
- int msg_type = CVAL(inbuf,0);
-
- chain_size = 0;
-
- if(Protocol >= PROTOCOL_LANMAN2)
- {
- if (lp_casesignames())
- casesignames = ((CVAL(inbuf,smb_flg) & 0x8) != 0x8);
- long_filenames = ((SVAL(inbuf, smb_flg2) & 0x1) != 0);
- }
-
- if (msg_type != 0)
- return(reply_special(inbuf,outbuf));
-
- memset(outbuf,0,smb_size);
-
- CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
- set_message(outbuf,0,0,True);
-
- memcpy(outbuf+4,inbuf+4,4);
- CVAL(outbuf,smb_rcls) = SUCCESS;
- CVAL(outbuf,smb_reh) = 0;
- CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set
- means a reply */
- CVAL(outbuf,smb_flg2) = (CVAL(inbuf,smb_flg2) & 1); /* say we support
- long filenames if
- he does */
- SSVAL(outbuf,smb_err,SUCCESS);
- SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
- SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
- SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
- SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
-
- outsize = switch_message(type,inbuf,outbuf,size,bufsize);
-
- if(outsize != -1)
- smb_setlen(outbuf,outsize - 4);
- return(outsize);
- }
-
-
- /****************************************************************************
- process commands from the client
- ****************************************************************************/
- void process(void )
- {
- static int trans_num = 0;
- int nread;
-
- InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
- OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
- if ((InBuffer == NULL) || (OutBuffer == NULL))
- return;
-
- DEBUG(3,("priming nmbd\n"));
- {
- struct in_addr ip;
- uint32 a = interpret_addr("localhost");
- memcpy(&ip,&a,4);
- *OutBuffer = 0;
- send_packet(OutBuffer,1,&ip,137,SOCK_DGRAM);
- }
-
-
- while (True)
- {
- int32 len;
- int msg_type;
- int msg_flags;
- int type;
- static BOOL all_down = False;
- int deadtime = lp_deadtime()*60*1000;
-
- if (all_down) /* automatic 3 minute deadtime if all
- connections are closed */
- deadtime = MAX(deadtime,180*1000);
-
- if (deadtime <= 0)
- deadtime = 1000*60*60*24*3; /* 3 days max timeout */
-
- if (lp_readprediction())
- do_read_prediction();
-
- if (done_become_user != -1)
- {
- if (!receive_smb(InBuffer,2*1000))
- {
- unbecome_user();
- if (!receive_smb(InBuffer,
- ((all_down || num_files_open == 0)?deadtime:0)))
- return;
- }
- }
- else
- {
- if (!receive_smb(InBuffer,(num_files_open == 0?deadtime:0)))
- return;
- }
-
- all_down = False;
-
- msg_type = CVAL(InBuffer,0);
- msg_flags = CVAL(InBuffer,1);
- type = CVAL(InBuffer,smb_com);
-
- len = smb_len(InBuffer);
-
- DEBUG(3,("got message type 0x%x of len 0x%x\n",msg_type,len));
-
- nread = len + 4;
-
- DEBUG(3,("%s Transaction %d\n",timestring(),trans_num));
-
- if (msg_type == 0)
- show_msg(InBuffer);
-
- nread = construct_reply(InBuffer,OutBuffer,nread,MIN(BUFFER_SIZE,lp_maxxmit()));
-
- if(nread > 0) {
- if (CVAL(OutBuffer,0) == 0)
- show_msg(OutBuffer);
-
- if (nread != smb_len(OutBuffer) + 4)
- {
- DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
- nread,
- smb_len(OutBuffer)));
- }
- else
- send_smb(OutBuffer);
- }
- trans_num++;
-
- /* If we got a tree disconnect, see if this was the
- last one in use, if so - exit */
- if(lp_deadtime() == 0 && type == SMBtdis)
- {
- int i;
- for(i=0;i<MAX_CONNECTIONS;i++)
- if(Connections[i].open)
- break; /* Stay in loop */
-
- if(i == MAX_CONNECTIONS)
- {
- all_down = True;
- DEBUG(3,("Last connection closed\n"));
- }
- }
- }
- }
-
-
- /****************************************************************************
- initialise connect, service and file structs
- ****************************************************************************/
- void init_structs(void )
- {
- int i;
- get_myname(myhostname,&myip);
-
- for (i=0;i<MAX_CONNECTIONS;i++)
- Connections[i].open = False;
- for (i=0;i<MAX_OPEN_FILES;i++)
- Files[i].open = False;
-
- num_files_open=0;
-
- init_dptrs();
- }
-
- /****************************************************************************
- usage on the program
- ****************************************************************************/
- void usage(char *pname)
- {
- DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
-
- printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\n",pname);
- printf("Version %s\n",VERSION);
- printf("\t-D become a daemon\n");
- printf("\t-p port listen on the specified port\n");
- printf("\t-d debuglevel set the debuglevel\n");
- printf("\t-l log basename. Basename for log/debug files\n");
- printf("\t-s services file. Filename of services file\n");
- printf("\t-P passive only\n");
- printf("\t-a overwrite log file, don't append\n");
- printf("\n");
- }
-
-
- /****************************************************************************
- main program
- ****************************************************************************/
- int main(int argc,char *argv[])
- {
- /* shall I run as a daemon */
- BOOL is_daemon = False;
- int port = 139;
- int opt;
- extern FILE *dbf;
- extern char *optarg;
-
- #ifdef SecureWare
- set_auth_parameters(argc,argv);
- setluid(0);
- #endif
-
- #ifdef OSF1_ENH_SEC
- set_auth_parameters();
- #endif
-
- sprintf(debugf,"%s.debug",DEBUGFILE);
-
- umask(0777 & ~DEF_CREATE_MASK);
-
- initial_uid = geteuid();
- initial_gid = getegid();
-
- if (initial_gid != 0 && initial_uid == 0)
- {
- #ifdef HPUX
- setresgid(0,0,0);
- #else
- setgid(0);
- setegid(0);
- #endif
- }
-
- initial_uid = geteuid();
- initial_gid = getegid();
-
- while ((opt = getopt (argc, argv, "i:l:s:d:Dp:hPa")) != EOF)
- switch (opt)
- {
- case 'i':
- strcpy(scope,optarg);
- break;
- case 'P':
- {
- extern BOOL passive;
- passive = True;
- }
- break;
- case 's':
- strcpy(servicesf,optarg);
- break;
- case 'l':
- sprintf(debugf,"%s.debug",optarg);
- break;
- case 'a':
- append_log = !append_log;
- break;
- case 'D':
- is_daemon = True;
- break;
- case 'd':
- if (*optarg == 'A')
- DEBUGLEVEL = 10000;
- else
- DEBUGLEVEL = atoi(optarg);
- break;
- case 'p':
- port = atoi(optarg);
- break;
- case 'h':
- usage(argv[0]);
- exit(0);
- break;
- default:
- usage(argv[0]);
- exit(1);
- }
-
-
- NeedSwap = big_endian();
-
- if (DEBUGLEVEL > 100)
- {
- extern FILE *login,*logout;
- pstring fname="";
- sprintf(fname,"%s.in",debugf);
- login = fopen(fname,"w");
- if (login) chmod(fname,0600);
- sprintf(fname,"%s.out",debugf);
- logout = fopen(fname,"w");
- if (logout) chmod(fname,0600);
- }
-
- if (DEBUGLEVEL > 0)
- {
- if (dbf)
- fclose(dbf);
- if (append_log)
- dbf = fopen(debugf,"a");
- else
- dbf = fopen(debugf,"w");
- if (dbf)
- setbuf(dbf,NULL);
- }
-
- DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
- DEBUG(2,("Copyright Andrew Tridgell 1992,1993,1994\n"));
-
- GetWd(OriginalDir);
- get_machine_info();
-
- DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
- getuid(),getgid(),geteuid(),getegid()));
-
- if (sizeof(uint32) != 4 || sizeof(int32) != 4)
- DEBUG(0,("WARNING! Your machine is incorrectly setup.\nYou must define int32 and uint32 to be 4 byte quantities\n"));
- if (sizeof(uint16) != 2 || sizeof(int16) != 2)
- DEBUG(0,("WARNING! Your machine is incorrectly setup.\nYou must define int16 and uint16 to be 2 byte quantities\n"));
-
- init_structs();
-
- if (!lp_load(servicesf))
- return(-1);
-
- if (DEBUGLEVEL > 1)
- DEBUG(3,("%s loaded services\n",timestring()));
-
- if (is_daemon)
- {
- DEBUG(3,("%s becoming a daemon\n",timestring()));
- become_daemon();
- }
-
- if (open_sockets(is_daemon,port))
- {
- /* reload the services file. It might have changed (if a daemon) */
- if (is_daemon && !lp_load(servicesf))
- return(-1);
-
- if (*lp_rootdir())
- {
- chroot(lp_rootdir());
-
- if (DEBUGLEVEL > 1)
- DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
- }
-
- maxxmit = lp_maxxmit();
-
- create_mangled_stack(lp_mangledstack());
- {
- extern BOOL use_getwd_cache;
- use_getwd_cache = lp_getwdcache();
- }
-
- process();
- close_sockets();
- }
- exit_server();
- return(0);
- }
-
-
-