--- samba-1.9.16p10/source/includes.h Tue Jan 28 19:01:37 1997 +++ samba-1.9.16p10_patch/source/includes.h Thu Feb 13 02:53:14 1997 @@ -19,6 +19,10 @@ 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. + + Changes for CIFS by O'DART linsupp@rphs1.physik.uni-regensburg.de + February 1997 + */ /* This file does all the #includes's. This makes it easier to @@ -237,6 +241,7 @@ Here come some platform specific section #endif #endif #endif +#include /* DART needed by makedev*/ #endif #ifdef SUNOS4 --- samba-1.9.16p10/source/server.c Tue Jan 28 19:01:40 1997 +++ samba-1.9.16p10_patch/source/server.c Thu Feb 13 02:53:19 1997 @@ -17,6 +17,9 @@ 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. + + Changes for CIFS by O'DART linsupp@rphs1.physik.uni-regensburg.de + February 1997 */ #include "includes.h" @@ -2681,7 +2684,7 @@ int reply_nt1(char *outbuf) SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */ SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */ - SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ + SIVAL(outbuf,smb_vwv9+1,capabilities | CAP_UNIX ); /* capabilities CAP_UNIX = 0x8000 DART*/ put_long_date(outbuf+smb_vwv11+1,t); SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); --- samba-1.9.16p10/source/smb.h Tue Jan 28 19:01:41 1997 +++ samba-1.9.16p10_patch/source/smb.h Thu Feb 13 02:53:33 1997 @@ -17,6 +17,9 @@ 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. + + Changes for CIFS by O'DART linsupp@rphs1.physik.uni-regensburg.de + February 1997 */ #ifndef _SMB_H #define _SMB_H @@ -217,6 +220,8 @@ implemented */ #define ERRnosupport 0xFFFF #define ERRunknownsmb 22 /* from NT 3.5 response */ +#define ErrQuota 999999 /* Quota exceeded */ +#define ErrNotALink 999999 /* link operation was performed on a pathname that was not a link */ /* Error codes for the ERRHRD class */ @@ -607,6 +612,8 @@ struct connect_record #define SMBfindnclose 0x35 /* Terminate a TRANSACT2_FINDNOTIFYFIRST */ #define SMBulogoffX 0x74 /* user logoff */ +/* Define the capability */ +#define CAP_UNIX 0x8000 /* capabilities for UN*X DART */ /* these are the TRANS2 sub commands */ #define TRANSACT2_OPEN 0 --- samba-1.9.16p10/source/system.c Tue Jan 28 19:01:41 1997 +++ samba-1.9.16p10_patch/source/system.c Thu Feb 13 02:53:33 1997 @@ -17,6 +17,10 @@ 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. + + Changes for CIFS by O'DART linsupp@rphs1.physik.uni-regensburg.de + February 1997 + */ #include "includes.h" @@ -184,6 +188,14 @@ int sys_chdir(char *dname) return(chdir(dos_to_unix(dname,False))); } +/******************************************************************* + readlink () +********************************************************************/ +int sys_readlink(char *fname, char *buf, size_t bufsiz) +{ + return(readlink(dos_to_unix(fname,False), buf, bufsiz)); +} + /******************************************************************* now for utime() @@ -235,3 +247,55 @@ int sys_chroot(char *dname) return(chroot(dname)); #endif } + +/* new DART */ +uint32 sys_filetype(uint32 mode) +{ + if(S_ISREG(mode)) /*Enumeration specifying the pathname type*/ + return 0; /* File */ + else if(S_ISDIR(mode)) + return 1; /* Dir */ + else if(S_ISLNK(mode)) + return 2; /* Symbolic link */ + else if(S_ISCHR(mode)) + return 3; /* Character device */ + else if(S_ISBLK(mode)) + return 4; /* Block device */ + else if(S_ISFIFO(mode)) + return 5; /* FIFO (named pipe) */ + else{ + DEBUG(0,("sys_filetype: unknown filetype %l",mode)); + return 0xFFFFFFFF; + } + +} + + +uint32 sys_makedev(uint32 maj, uint32 min) +{ +#ifdef LINUX + return (makedev(maj & 0xff, min & 0xff )); +#else + return (makedevice(maj & 0xff, min & 0xff )); +#endif + + /* major and minornumber are common in dev_type*/ + /* see /usr/include/linux/kdev_t.h; /usr/include/sys/sysmacros.h */ +} + +int sys_mknod(char *fname, uint32 mode, uint32 file_type, uint32 major, uint32 minor) +{ + switch(file_type){ + case 3: /* charakter device */ + return mknod(dos_to_unix(fname,False),mode | S_IFCHR,sys_makedev(major,minor)); + break; + case 4: /* block device */ + return mknod(dos_to_unix(fname,False),mode | S_IFBLK,sys_makedev(major,minor)); + break; + case 5: /* FIFO */ + return mknod(dos_to_unix(fname,False),mode | S_IFIFO,sys_makedev(major,minor)); + break; + } + return 1; /* don't know */ +} + --- samba-1.9.16p10/source/trans2.c Tue Jan 28 19:01:41 1997 +++ samba-1.9.16p10_patch/source/trans2.c Thu Feb 13 02:53:33 1997 @@ -19,6 +19,10 @@ 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. + + Changes for CIFS by O'DART linsupp@rphs1.physik.uni-regensburg.de + February 1997 + */ #include "includes.h" @@ -324,12 +328,20 @@ static int get_lanman2_dir_entry(int cnu strcpy(pathreal,Connections[cnum].dirpath); strcat(pathreal,"/"); strcat(pathreal,fname); - if (sys_stat(pathreal,&sbuf) != 0) - { - DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); - continue; - } - + if (info_level < SMB_FIND_FILE_UNIX){ + if (sys_stat(pathreal,&sbuf) != 0) + { + DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); + continue; + } + } + else{ + if (sys_lstat(pathreal,&sbuf) != 0) { + DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",pathreal,strerror(errno))); + continue; + } + } + mode = dos_mode(cnum,pathreal,&sbuf); if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) { @@ -503,6 +515,51 @@ static int get_lanman2_dir_entry(int cnu p = pdata + len; break; + case SMB_FIND_FILE_UNIX: /*DART*/ + len = 76+strlen(fname)+1; /* (lenght of SMB_QUERY_FILE_UNIX_BASIC = 68)+4+4+strlen(fname)*/ + /* +1 to be sure to transmit the termination of fname */ + len = (len + 3) & ~3; + + /* using pdata instead of p to have analogy to call_trans2qfilepathinfo*/ + SIVAL(pdata,0,len); pdata += 4; /* Offset from this structure to the beginning of the next one */ + SIVAL(pdata,0,reskey); pdata += 4; /* Used for continuing search. */ + + /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ + SIVAL(pdata,0,sbuf.st_size); /* File size 64 Bit */ + SIVAL(pdata,4,0); + pdata += 8; + put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */ + put_long_date(pdata+8,sbuf.st_atime); /* Last access time 64 bit*/ + put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time 64 bit*/ + pdata += 24; + SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */ + SIVAL(pdata,4,sbuf.st_gid); /* group id of owner */ + pdata += 8 ; + + SIVAL(pdata,0,sys_filetype(sbuf.st_mode)); + + pdata += 4; + /* SIVAL(pdata,0,sbuf.st_rdev >>8); */ + SIVAL(pdata,0,major(sbuf.st_rdev)); /* Major device number if type is device */ + /* SIVAL(pdata,4,sbuf.st_rdev & 0xff);*/ + SIVAL(pdata,4,minor(sbuf.st_rdev)); /* Minor device number if type is device */ + pdata += 8; + + SIVAL(pdata,0,sbuf.st_ino); /* inode number */ + SIVAL(pdata,4,0); + pdata += 8; + + SIVAL(pdata,0,sbuf.st_mode & 0xFFF ); /* Standard UNIX file permissions */ + SIVAL(pdata,4,sbuf.st_nlink); /* number of hard links */ + pdata += 8; + + /* End of SMB_QUERY_FILE_UNIX_BASIC */ + strcpy(pdata,fname); + pdata=p; /* Going back to p - convention */ + p=pdata+len; + + break; + default: return(False); } @@ -571,6 +628,7 @@ static int call_trans2findfirst(char *in case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + case SMB_FIND_FILE_UNIX: /*DART*/ break; default: return(ERROR(ERRDOS,ERRunknownlevel)); @@ -761,6 +819,7 @@ static int call_trans2findnext(char *inb case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + case SMB_FIND_FILE_UNIX: /*DART*/ break; default: return(ERROR(ERRDOS,ERRunknownlevel)); @@ -1004,6 +1063,8 @@ static int call_trans2qfilepathinfo(char char *fname; char *p; int l,pos; + char buffer[PATH_MAX+1]; /*DART*/ + int len, i; if (tran_call == TRANSACT2_QFILEINFO) { @@ -1025,10 +1086,18 @@ static int call_trans2qfilepathinfo(char fname = &fname1[0]; strcpy(fname,¶ms[6]); unix_convert(fname,cnum,0); - if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return(UNIXERROR(ERRDOS,ERRbadpath)); + if (info_level < SMB_QUERY_FILE_UNIX_BASIC){ + if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) { + DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + return(UNIXERROR(ERRDOS,ERRbadpath)); + } } + else { + if (!check_name(fname,cnum) || sys_lstat(fname,&sbuf)) { + DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + } pos = 0; } @@ -1169,6 +1238,58 @@ static int call_trans2qfilepathinfo(char SIVAL(pdata,20,l); strcpy(pdata+24,fname); break; + + case SMB_QUERY_FILE_UNIX_BASIC: /* DART */ + DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",sbuf.st_mode)); + SIVAL(pdata,0,sbuf.st_size); /* File size 64 Bit */ + SIVAL(pdata,4,0); + pdata += 8; + put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */ + put_long_date(pdata+8,sbuf.st_atime); /* Last access time */ + put_long_date(pdata+16,sbuf.st_mtime); /* Last modification time */ + pdata += 24; + SIVAL(pdata,0,sbuf.st_uid); /* user id for the owner */ + SIVAL(pdata,4,sbuf.st_gid); /* group id of owner */ + pdata += 8 ; + + SIVAL(pdata,0,sys_filetype(sbuf.st_mode)); + + pdata += 4; + /* SIVAL(pdata,0,sbuf.st_rdev >>8); */ + SIVAL(pdata,0,major(sbuf.st_rdev)); /* Major device number if type is device */ + /* SIVAL(pdata,4,sbuf.st_rdev & 0xff);*/ + SIVAL(pdata,4,minor(sbuf.st_rdev)); /* Minor device number if type is device */ + + pdata += 8; + + SIVAL(pdata,0,sbuf.st_ino); /* inode number */ + SIVAL(pdata,4,0); + pdata += 8; + + SIVAL(pdata,0,sbuf.st_mode & 0xFFF ); /* Standard UNIX file permissions */ + SIVAL(pdata,4,sbuf.st_nlink); /* number of hard links */ + pdata += 8+1; + data_size = PTR_DIFF(pdata,(*ppdata)); + + DEBUG(4,("call_trans2qfilepathinfo: ")); + + for (i=0; i<68; i++) + DEBUG(4,("%d=%x, ",i, (*ppdata)[i])); + + break; + + case SMB_QUERY_FILE_UNIX_LINK: /* DART */ + if(!S_ISLNK(sbuf.st_mode)) + return(UNIXERROR(ERRDOS,ErrNotALink)); + len = sys_readlink(fname, buffer, PATH_MAX); /* read link */ + buffer[len] = 0; + strcpy(pdata,buffer); /* write '\0' terminated string */ + pdata += strlen(buffer)+1; + data_size = PTR_DIFF(pdata,(*ppdata)); + + break; + + default: return(ERROR(ERRDOS,ERRunknownlevel)); } @@ -1189,7 +1310,7 @@ static int call_trans2setfilepathinfo(ch char *pdata = *ppdata; uint16 tran_call = SVAL(inbuf, smb_setup0); uint16 info_level; - int mode=0; + uint32 mode=0; /*DART (was int) */ int size=0; struct utimbuf tvs; struct stat st; @@ -1197,6 +1318,16 @@ static int call_trans2setfilepathinfo(ch char *fname; int fd = -1; + uint32 owner; /*DART*/ + uint32 group; + uint32 st_owner; + uint32 st_group; + uint32 st_mode; + uint32 file_type=-1; + uint32 dev_type,cifs_major,cifs_minor; + int stat_ret; + char link_dest[PATH_MAX+1]; /*end*/ + if (!CAN_WRITE(cnum)) return(ERROR(ERRSRV,ERRaccess)); @@ -1210,7 +1341,7 @@ static int call_trans2setfilepathinfo(ch fname = Files[fnum].name; fd = Files[fnum].fd_ptr->fd; - if(fstat(fd,&st)!=0) { + if((stat_ret=fstat(fd,&st))!=0) { DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); return(ERROR(ERRDOS,ERRbadpath)); } @@ -1223,7 +1354,7 @@ static int call_trans2setfilepathinfo(ch if(!check_name(fname, cnum)) return(ERROR(ERRDOS,ERRbadpath)); - if(sys_stat(fname,&st)!=0) { + if((stat_ret=sys_stat(fname,&st))!=0 && info_level < SMB_SET_FILE_UNIX_BASIC) { DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); return(ERROR(ERRDOS,ERRbadpath)); } @@ -1242,6 +1373,13 @@ static int call_trans2setfilepathinfo(ch tvs.actime = st.st_atime; mode = dos_mode(cnum,fname,&st); + st_owner = st.st_uid; /* DART */ + st_group = st.st_gid; + st_mode = st.st_mode & 0xFFF; /* only permissions */ + owner = st.st_uid; + group = st.st_gid; + /* end*/ + if (total_data > 0 && IVAL(pdata,0) == total_data) { /* uggh, EAs for OS2 */ DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); @@ -1296,6 +1434,38 @@ static int call_trans2setfilepathinfo(ch size = IVAL(pdata,0); break; + case SMB_SET_FILE_UNIX_BASIC: /* DART */ + size=IVAL(pdata,0); /* first 4 Bites are size */ + pdata+=16; /* ctime is not changed */ + tvs.actime = interpret_long_date(pdata); /* access_time */ + tvs.actime = interpret_long_date(pdata+8); /* modification_time */ + pdata+=16; + owner=IVAL(pdata,0); + group=IVAL(pdata,4); + file_type=IVAL(pdata,8); + if( stat_ret!=0 && file_type<3 ){ /* 0: File ; 1: Directory; 2: Link */ + DEBUG(3,("stat of %s failed in SMB_SET_FILE_UNIX_BASIC\n", fname)); + return(ERROR(ERRDOS,ERRbadpath)); + } + pdata+=12; + + cifs_major=IVAL(pdata,0); + cifs_minor=IVAL(pdata,4); + + pdata+=16; /* ignore uniqueid, don't used here */ + mode=IVAL(pdata,0); /* get unix-permissions */ + pdata+=8; /* number of hard links can't be set here !*/ + break; + + case SMB_SET_FILE_UNIX_LINK: + if(stat_ret == 0){ + DEBUG(0,("can't change the Link :%s\n", fname)); + return(ERROR(ERRSRV,ERRaccess)); + } + strncpy(link_dest,pdata,PATH_MAX); + link_dest[PATH_MAX]=0; + break; + case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */ case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */ default: @@ -1307,16 +1477,77 @@ static int call_trans2setfilepathinfo(ch if (!tvs.modtime) tvs.modtime = st.st_mtime; if (!size) size = st.st_size; + if( info_level == SMB_SET_FILE_UNIX_BASIC ){ + if( stat_ret!=0 ){ /* o.k. nod doesn't exist yet */ + DEBUG(5,("try mknod of %s : filetype: %ld ; mode: %ld\n", fname,file_type,mode)); + if(sys_mknod(fname,mode,file_type,cifs_major,cifs_minor)!=0){ /* create nod */ + DEBUG(0,("can't creat nod %ld: %s (%s)\n", file_type,fname,strerror(errno))); + return(ERROR(ERRSRV,ERRaccess)); + } + st_mode=mode+1; /* so we must change the mode see below */ + } + + /* lets check if we can chown to the user and the group */ + st_owner=geteuid(); + + DEBUG(5,("try chown now %s ; owner: %ld ; group: %ld ; st_owner\n", fname,owner,group,st_owner)); + if(st_owner != 0 && st_owner != owner ){ /* not root + owner & user differ */ + if ( stat_ret!=0 ) sys_unlink(fname); + DEBUG(0,("not permitted to change owner (filetype: %ld) of %s to owner %ld as user: %ld\n", file_type,fname,owner,st_owner)); + return(ERROR(ERRSRV,ERRaccess)); + } + else if(st_owner == 0 && st_owner != owner){ /* root ->try to change owner */ + DEBUG(5,("try chown of %s ; owner: %ld ; group: %ld\n", fname,owner,group)); + if(sys_chown(fname,owner,group)!=0){ + DEBUG(0,("can't chown %s filetype: %ld ;owner %ld ; group: %ld(errno: %s)\n", fname,file_type,owner,group,strerror(errno))); + if ( stat_ret!=0 )sys_unlink(fname); + return(ERROR(ERRSRV,ERRaccess)); + } + st_owner=owner; + st_group=group; + } + DEBUG(5,("try chown done %s ; owner: %ld ; group: %ld ; st_owner\n", fname,owner,group,st_owner)); + + if(st_group != group){ /* group differ -> try to change */ + DEBUG(5,("try chgrp of %s to %ld\n", fname,group)); + if(sys_chown(fname,-1,group)!=0){ /* don't change owner ( only root is permited to) */ + DEBUG(0,("can't chown %s filetype: %ld ;to group %ld (errno: %s)\n", fname,file_type,group,strerror(errno))); + if ( stat_ret!=0 ) sys_unlink(fname); + return(ERROR(ERRSRV,ERRaccess)); + } + } + + DEBUG(5,("try chmod of %s to %o\n", fname,mode)); + if(st_mode != mode && sys_chmod(fname,mode)!=0){ + DEBUG(0,("chmod of %s failed (%s)\n", fname, strerror(errno))); + return(ERROR(ERRSRV,ERRaccess)); + } + + } + else if(info_level == SMB_SET_FILE_UNIX_LINK){ + DEBUG(5,("try to create a link; dest: %s ; from %s\n",link_dest,fname)); + if( symlink(link_dest,fname)!=0 ){ + DEBUG(0,("can't create symlink , dest: %s , source: %s (err: %s)\n", link_dest,fname, strerror(errno))); + return(ERROR(ERRSRV,ERRaccess)); + } + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } + else{ /* info_level