From ebcfab8d3247ff6fa98726c88a55a5cec0d91f97 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 28 Jul 2006 14:36:24 +0000 Subject: [PATCH] windows-cifs-compatibility-20060728 more compatibility fixes to the CIFS gateway server --- src/WINNT/afsd/fs.c | 2 +- src/WINNT/afsd/smb.c | 22 +++++ src/WINNT/afsd/smb.h | 9 +- src/WINNT/afsd/smb3.c | 197 +++++++++++++++++++++++++++++++----------- src/WINNT/afsd/smb3.h | 11 ++- 5 files changed, 183 insertions(+), 58 deletions(-) diff --git a/src/WINNT/afsd/fs.c b/src/WINNT/afsd/fs.c index ed5db81b3..fb43d87c1 100644 --- a/src/WINNT/afsd/fs.c +++ b/src/WINNT/afsd/fs.c @@ -2280,7 +2280,7 @@ GetCacheParmsCmd(struct cmd_syndesc *as, char *arock) { afs_int32 code; struct ViceIoctl blob; - afs_int32 parms[MAXGCSIZE]; + afs_uint64 parms[MAXGCSIZE]; memset(parms, 0, sizeof(parms)); blob.in = NULL; diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 297b1f76a..2043d6d2c 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -444,6 +444,8 @@ char * myCrt_2Dispatch(int i) return "S(0d)_ReceiveTran2CreateDirectory"; case 14: return "S(0e)_ReceiveTran2SessionSetup"; + case 15: + return "S(0f)_QueryFileSystemInformationFid"; case 16: return "S(10)_ReceiveTran2GetDfsReferral"; case 17: @@ -1505,6 +1507,25 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags) return fidp; } +smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp) +{ + smb_fid_t *fidp = NULL; + int newFid = 0; + + if (!scp) + return NULL; + + lock_ObtainWrite(&smb_rctLock); + for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) { + if (scp == fidp->scp) { + fidp->refCount++; + break; + } + } + lock_ReleaseWrite(&smb_rctLock); + return fidp; +} + void smb_HoldFIDNoLock(smb_fid_t *fidp) { fidp->refCount++; @@ -8775,6 +8796,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt, smb_tran2DispatchTable[12].procp = smb_ReceiveTran2FindNotifyNext; smb_tran2DispatchTable[13].procp = smb_ReceiveTran2CreateDirectory; smb_tran2DispatchTable[14].procp = smb_ReceiveTran2SessionSetup; + smb_tran2DispatchTable[15].procp = smb_ReceiveTran2QFSInfoFid; smb_tran2DispatchTable[16].procp = smb_ReceiveTran2GetDFSReferral; smb_tran2DispatchTable[17].procp = smb_ReceiveTran2ReportDFSInconsistency; diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index b88bd24b3..6f49c52b5 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -93,10 +93,13 @@ typedef struct smb { #define SMB_INFO_ALLOCATION 1 #define SMB_INFO_VOLUME 2 +#define SMB_QUERY_FS_LABEL_INFO 0x101 #define SMB_QUERY_FS_VOLUME_INFO 0x102 #define SMB_QUERY_FS_SIZE_INFO 0x103 #define SMB_QUERY_FS_DEVICE_INFO 0x104 #define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105 +#define SMB_QUERY_FS_QUOTA_INFO 0x106 +#define SMB_QUERY_FS_CONTROL_INFO 0x107 #define SMB_INFO_UNIX 0x200 #define SMB_INFO_MACOS 0x301 @@ -572,6 +575,8 @@ extern long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, char ** tidPath extern smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags); +extern smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp); + extern void smb_HoldFIDNoLock(smb_fid_t *fidp); extern void smb_ReleaseFID(smb_fid_t *fidp); @@ -701,10 +706,6 @@ extern unsigned int smb_Attributes(cm_scache_t *scp); extern int smb_ChainFID(int fid, smb_packet_t *inp); -extern smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags); - -extern void smb_ReleaseFID(smb_fid_t *fidp); - extern unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp); extern unsigned char *smb_ParseASCIIBlock(unsigned char *inp, char **chainpp); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 47c968b3b..5ef184036 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -2433,12 +2433,24 @@ long smb_ReceiveTran2FindNext(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t return CM_ERROR_BADOP; } +long smb_ReceiveTran2QFSInfoFid(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) +{ + unsigned short fid; + unsigned short infolevel; + + infolevel = p->parmsp[0]; + fid = p->parmsp[1]; + osi_Log2(smb_logp, "T2 QFSInfoFid InfoLevel 0x%x fid 0x%x - NOT_SUPPORTED", infolevel, fid); + + return CM_ERROR_BADOP; +} + long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { smb_tran2Packet_t *outp; smb_tran2QFSInfo_t qi; int responseSize; - static char FSname[6] = {'A', 0, 'F', 0, 'S', 0}; + static char FSname[8] = {'A', 0, 'F', 0, 'S', 0, 0, 0}; osi_Log1(smb_logp, "T2 QFSInfo type 0x%x", p->parmsp[0]); @@ -2492,7 +2504,7 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t * memset((char *)&qi.u.FSvolumeInfo.vct, 0, 4); qi.u.FSvolumeInfo.vsn = 1234; qi.u.FSvolumeInfo.vnCount = 8; - memcpy(qi.u.FSvolumeInfo.label, "A\0F\0S\0\0", 8); + memcpy(qi.u.FSvolumeInfo.label, "A\0F\0S\0\0\0", 8); break; case SMB_QUERY_FS_SIZE_INFO: @@ -2522,10 +2534,10 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t * * we can't handle long (non-8.3) names, * despite our protestations to the contrary. */ - qi.u.FSattributeInfo.attributes = 0x4013; - qi.u.FSattributeInfo.maxCompLength = 255; - qi.u.FSattributeInfo.FSnameLength = 6; - memcpy(qi.u.FSattributeInfo.FSname, FSname, 6); + qi.u.FSattributeInfo.attributes = 0x4003; + qi.u.FSattributeInfo.maxCompLength = MAX_PATH; + qi.u.FSattributeInfo.FSnameLength = sizeof(FSname); + memcpy(qi.u.FSattributeInfo.FSname, FSname, sizeof(FSname)); break; } @@ -2637,8 +2649,6 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t cm_user_t *userp; cm_space_t *spacep; cm_scache_t *scp, *dscp; - smb_fid_t *fidp; - unsigned short fid; int delonclose = 0; long code = 0; char *pathp; @@ -2648,16 +2658,6 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t cm_InitReq(&req); - fid = p->parmsp[0]; - fidp = smb_FindFID(vcp, fid, 0); - if (fidp) { - lock_ObtainMutex(&fidp->mx); - delonclose = fidp->flags & SMB_FID_DELONCLOSE; - lock_ReleaseMutex(&fidp->mx); - smb_ReleaseFID(fidp); - fidp = NULL; - } - infoLevel = p->parmsp[0]; if (infoLevel == SMB_INFO_IS_NAME_VALID) responseSize = 0; @@ -2825,15 +2825,15 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t goto done; } - qpi.u.QPfileAltNameInfo.fileNameLength = len * 2; - mbstowcs((unsigned short *)qpi.u.QPfileAltNameInfo.fileName, shortName, len); + qpi.u.QPfileAltNameInfo.fileNameLength = (len + 1) * 2; + mbstowcs((unsigned short *)qpi.u.QPfileAltNameInfo.fileName, shortName, len + 1); goto done; } else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) { len = strlen(lastComp); - qpi.u.QPfileNameInfo.fileNameLength = len * 2; - mbstowcs((unsigned short *)qpi.u.QPfileNameInfo.fileName, lastComp, len); + qpi.u.QPfileNameInfo.fileNameLength = (len + 1) * 2; + mbstowcs((unsigned short *)qpi.u.QPfileNameInfo.fileName, lastComp, len + 1); goto done; } @@ -2856,8 +2856,17 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t qpi.u.QPfileBasicInfo.changeTime = ft; extAttributes = smb_ExtAttributes(scp); qpi.u.QPfileBasicInfo.attributes = extAttributes; + qpi.u.QPfileBasicInfo.reserved = 0; } else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) { + smb_fid_t *fidp = smb_FindFIDByScache(vcp, scp); + if (fidp) { + lock_ObtainMutex(&fidp->mx); + delonclose = fidp->flags & SMB_FID_DELONCLOSE; + lock_ReleaseMutex(&fidp->mx); + smb_ReleaseFID(fidp); + } + qpi.u.QPfileStandardInfo.allocationSize = scp->length; qpi.u.QPfileStandardInfo.endOfFile = scp->length; qpi.u.QPfileStandardInfo.numberOfLinks = scp->linkCount; @@ -2866,6 +2875,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t ((scp->fileType == CM_SCACHETYPE_DIRECTORY || scp->fileType == CM_SCACHETYPE_MOUNTPOINT || scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); + qpi.u.QPfileStandardInfo.reserved = 0; } else if (infoLevel == SMB_QUERY_FILE_EA_INFO) { qpi.u.QPfileEaInfo.eaSize = 0; @@ -2897,8 +2907,8 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t qpi.u.QPfileAllInfo.mode = 0; qpi.u.QPfileAllInfo.alignmentRequirement = 0; len = strlen(lastComp); - qpi.u.QPfileAllInfo.fileNameLength = len * 2; - mbstowcs((unsigned short *)qpi.u.QPfileAllInfo.fileName, lastComp, len); + qpi.u.QPfileAllInfo.fileNameLength = (len + 1) * 2; + mbstowcs((unsigned short *)qpi.u.QPfileAllInfo.fileName, lastComp, len + 1); } /* send and free the packets */ @@ -2924,34 +2934,129 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet return CM_ERROR_BADOP; #else long code = 0; - unsigned short fid; smb_fid_t *fidp; unsigned short infoLevel; + char * pathp; smb_tran2Packet_t *outp; smb_tran2QPathInfo_t *spi; cm_user_t *userp; - cm_scache_t *scp; + cm_scache_t *scp, *dscp; cm_req_t req; + cm_space_t *spacep; + char *tidPathp; + char *lastComp; cm_InitReq(&req); - fid = p->parmsp[0]; - fidp = smb_FindFID(vcp, fid, 0); - - if (fidp == NULL) { - smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD); - return 0; - } - - infoLevel = p->parmsp[1]; - osi_Log2(smb_logp,"ReceiveTran2SetPathInfo type 0x%x fid %d", infoLevel, fid); + infoLevel = p->parmsp[0]; + osi_Log1(smb_logp,"ReceiveTran2SetPathInfo type 0x%x", infoLevel); if (infoLevel != SMB_INFO_STANDARD && infoLevel != SMB_INFO_QUERY_EA_SIZE && infoLevel != SMB_INFO_QUERY_ALL_EAS) { osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x", p->opcode, infoLevel); smb_SendTran2Error(vcp, p, opx, CM_ERROR_INVAL); - smb_ReleaseFID(fidp); + return 0; + } + + pathp = (char *)(&p->parmsp[3]); + if (smb_StoreAnsiFilenames) + OemToChar(pathp,pathp); + osi_Log2(smb_logp, "T2 SetPathInfo infolevel 0x%x path %s", infoLevel, + osi_LogSaveString(smb_logp, pathp)); + + userp = smb_GetTran2User(vcp, p); + if (!userp) { + osi_Log1(smb_logp,"ReceiveTran2SetPathInfo unable to resolve user [%d]", p->uid); + code = CM_ERROR_BADSMB; + goto done; + } + + code = smb_LookupTIDPath(vcp, p->tid, &tidPathp); + if (code == CM_ERROR_TIDIPC) { + /* Attempt to use a TID allocated for IPC. The client + * is probably looking for DCE RPC end points which we + * don't support OR it could be looking to make a DFS + * referral request. + */ + osi_Log0(smb_logp, "Tran2Open received IPC TID"); + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } + + /* + * XXX Strange hack XXX + * + * As of Patch 7 (13 January 98), we are having the following problem: + * In NT Explorer 4.0, whenever we click on a directory, AFS gets + * requests to look up "desktop.ini" in all the subdirectories. + * This can cause zillions of timeouts looking up non-existent cells + * and volumes, especially in the top-level directory. + * + * We have not found any way to avoid this or work around it except + * to explicitly ignore the requests for mount points that haven't + * yet been evaluated and for directories that haven't yet been + * fetched. + */ + if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) { + spacep = cm_GetSpace(); + smb_StripLastComponent(spacep->data, &lastComp, pathp); +#ifndef SPECIAL_FOLDERS + /* Make sure that lastComp is not NULL */ + if (lastComp) { + if (stricmp(lastComp, "\\desktop.ini") == 0) { + code = cm_NameI(cm_data.rootSCachep, spacep->data, + CM_FLAG_CASEFOLD + | CM_FLAG_DIRSEARCH + | CM_FLAG_FOLLOW, + userp, tidPathp, &req, &dscp); + if (code == 0) { +#ifdef DFS_SUPPORT + if (dscp->fileType == CM_SCACHETYPE_DFSLINK) { + if ( WANTS_DFS_PATHNAMES(p) ) + code = CM_ERROR_PATH_NOT_COVERED; + else + code = CM_ERROR_BADSHARENAME; + } else +#endif /* DFS_SUPPORT */ + if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume) + code = CM_ERROR_NOSUCHFILE; + else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) { + cm_buf_t *bp = buf_Find(dscp, &hzero); + if (bp) + buf_Release(bp); + else + code = CM_ERROR_NOSUCHFILE; + } + cm_ReleaseSCache(dscp); + if (code) { + cm_FreeSpace(spacep); + cm_ReleaseUser(userp); + smb_SendTran2Error(vcp, p, opx, code); + return 0; + } + } + } + } +#endif /* SPECIAL_FOLDERS */ + + cm_FreeSpace(spacep); + } + + /* now do namei and stat, and copy out the info */ + code = cm_NameI(cm_data.rootSCachep, pathp, + CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp); + if (code) { + cm_ReleaseUser(userp); + smb_SendTran2Error(vcp, p, opx, code); + return 0; + } + + fidp = smb_FindFIDByScache(vcp, scp); + if (!fidp) { + cm_ReleaseUser(userp); + cm_ReleaseSCache(scp); + smb_SendTran2Error(vcp, p, opx, code); return 0; } @@ -2959,12 +3064,11 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet if (!(fidp->flags & SMB_FID_OPENWRITE)) { lock_ReleaseMutex(&fidp->mx); smb_ReleaseFID(fidp); + cm_ReleaseUser(userp); + cm_ReleaseSCache(scp); smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOACCESS); return 0; } - - scp = fidp->scp; - cm_HoldSCache(scp); lock_ReleaseMutex(&fidp->mx); outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, 0); @@ -2972,13 +3076,6 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet outp->totalParms = 2; outp->totalData = 0; - userp = smb_GetTran2User(vcp, p); - if (!userp) { - osi_Log1(smb_logp,"ReceiveTran2SetPathInfo unable to resolve user [%d]", p->uid); - code = CM_ERROR_BADSMB; - goto done; - } - spi = (smb_tran2QPathInfo_t *)p->datap; if (infoLevel == SMB_INFO_STANDARD || infoLevel == SMB_INFO_QUERY_EA_SIZE) { cm_attr_t attr; @@ -3159,9 +3256,9 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t name = "\\"; /* probably can't happen */ lock_ReleaseMutex(&fidp->mx); len = (unsigned long)strlen(name); - outp->totalData = (len*2) + 4; /* this is actually what we want to return */ - qfi.u.QFfileNameInfo.fileNameLength = len * 2; - mbstowcs((unsigned short *)qfi.u.QFfileNameInfo.fileName, name, len); + outp->totalData = ((len+1)*2) + 4; /* this is actually what we want to return */ + qfi.u.QFfileNameInfo.fileNameLength = (len + 1) * 2; + mbstowcs((unsigned short *)qfi.u.QFfileNameInfo.fileName, name, len + 1); } /* send and free the packets */ diff --git a/src/WINNT/afsd/smb3.h b/src/WINNT/afsd/smb3.h index b6e86b7c9..813c33a7a 100644 --- a/src/WINNT/afsd/smb3.h +++ b/src/WINNT/afsd/smb3.h @@ -119,7 +119,8 @@ typedef struct { FILETIME lastAccessTime; FILETIME lastWriteTime; FILETIME changeTime; - unsigned short attributes; + unsigned long attributes; + unsigned long reserved; } QPfileBasicInfo; struct { LARGE_INTEGER allocationSize; @@ -127,6 +128,7 @@ typedef struct { unsigned long numberOfLinks; unsigned char deletePending; unsigned char directory; + unsigned short reserved; } QPfileStandardInfo; struct { unsigned long eaSize; @@ -140,7 +142,7 @@ typedef struct { FILETIME lastAccessTime; FILETIME lastWriteTime; FILETIME changeTime; - unsigned short attributes; + unsigned long attributes; LARGE_INTEGER allocationSize; LARGE_INTEGER endOfFile; unsigned long numberOfLinks; @@ -185,7 +187,7 @@ typedef struct { FILETIME lastAccessTime; FILETIME lastWriteTime; FILETIME lastChangeTime; - unsigned short attributes; + unsigned long attributes; } QFbasicInfo; struct { LARGE_INTEGER allocationSize; @@ -247,6 +249,9 @@ extern long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, extern long smb_ReceiveTran2SetFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp); +extern long smb_ReceiveTran2QFSInfoFid(smb_vc_t *vcp, smb_tran2Packet_t *p, + smb_packet_t *outp); + extern long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp); -- 2.39.5