#ifndef DJGPP
#include <windows.h>
+#include <ntstatus.h>
#define SECURITY_WIN32
#include <security.h>
#include <lmaccess.h>
#include <osi.h>
#include "afsd.h"
+#include <WINNT\afsreg.h>
#include "smb.h"
unsigned long attrs;
if (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
- scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_INVALID)
{
attrs = SMB_ATTR_DIRECTORY;
#ifdef SPECIAL_FOLDERS
attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
#endif /* SPECIAL_FOLDERS */
+ } else if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
} else
attrs = 0;
/*
*/
#ifdef notdef
if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+ attrs |= SMB_ATTR_READONLY; /* Read-only */
+#else
+ if ((scp->unixModeBits & 0222) == 0)
+ attrs |= SMB_ATTR_READONLY; /* Read-only */
#endif
- if ((scp->unixModeBits & 0222) == 0)
- attrs |= SMB_ATTR_READONLY; /* Read-only */
if (attrs == 0)
attrs = SMB_ATTR_NORMAL; /* FILE_ATTRIBUTE_NORMAL */
char tc;
while (tc = *maskp++)
- if (tc == '?' || tc == '*')
+ if (tc == '?' || tc == '*' || tc == '<' || tc == '>')
return 1;
return 0;
}
"aLimits,
&ntsEx);
+ if (nts != STATUS_SUCCESS || ntsEx != STATUS_SUCCESS)
+ osi_Log2(smb_logp,"LsaLogonUser failure: nts %u ntsEx %u",
+ nts, ntsEx);
+
OutputDebugF("Return from LsaLogonUser is 0x%lX", nts);
OutputDebugF("Extended status is 0x%lX", ntsEx);
if (s1 == NULL) {s1 = s2; s2 = " ";}
osi_Log4(smb_logp, "SMB3 user logoffX uid %d name %s%s%s", uidp->userID,
- osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "), s1, s2);
+ osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "),
+ osi_LogSaveString(smb_logp,s1), osi_LogSaveString(smb_logp,s2));
lock_ObtainMutex(&uidp->mx);
uidp->flags |= SMB_USERFLAG_DELETE;
((smb_t *)inp)->tid = newTid;
tp = smb_GetSMBData(outp, NULL);
if (!ipc) {
- /* XXX - why is this a drive letter? - jaltman */
+ /* XXX - why is this a drive letter? */
*tp++ = 'A';
*tp++ = ':';
*tp++ = 0;
- smb_SetSMBDataLength(outp, 3);
+ *tp++ = 'N';
+ *tp++ = 'T';
+ *tp++ = 'F';
+ *tp++ = 'S';
+ *tp++ = 0;
+ smb_SetSMBDataLength(outp, 8);
} else {
strcpy(tp, "IPC");
smb_SetSMBDataLength(outp, 4);
smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
- smbp->flg2 |= SMB_FLAGS2_ERR_STATUS;
+ smbp->flg2 |= SMB_FLAGS2_32BIT_STATUS;
}
else {
smbp->rcls = errClass;
}
/* first figure out how many shares there are */
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0,
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0,
KEY_QUERY_VALUE, &hkParam);
if (rv == ERROR_SUCCESS) {
len = sizeof(allSubmount);
RegCloseKey (hkParam);
}
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\Submounts",
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
0, KEY_QUERY_VALUE, &hkSubmount);
if (rv == ERROR_SUCCESS) {
rv = RegQueryInfoKey(hkSubmount, NULL, NULL, NULL, NULL,
thyper.HighPart = 0;
thyper.LowPart = 0;
- cm_HoldSCache(cm_rootSCachep);
- cm_ApplyDir(cm_rootSCachep, smb_rapCollectSharesProc, &rootShares, &thyper, userp, &req, NULL);
- cm_ReleaseSCache(cm_rootSCachep);
+ cm_HoldSCache(cm_data.rootSCachep);
+ cm_ApplyDir(cm_data.rootSCachep, smb_rapCollectSharesProc, &rootShares, &thyper, userp, &req, NULL);
+ cm_ReleaseSCache(cm_data.rootSCachep);
cm_ReleaseUser(userp);
outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParam, totalData);
if(!stricmp(shareName,"all")) {
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0,
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0,
KEY_QUERY_VALUE, &hkParam);
if (rv == ERROR_SUCCESS) {
len = sizeof(allSubmount);
shareFound = TRUE;
} else {
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\Submounts", 0,
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY "\\Submounts", 0,
KEY_QUERY_VALUE, &hkSubmount);
if (rv == ERROR_SUCCESS) {
rv = RegQueryValueEx(hkSubmount, shareName, NULL, NULL, NULL, NULL);
smb_fid_t *fidp;
int attributes;
char *lastNamep;
- time_t dosTime;
+ afs_uint32 dosTime;
int openFun;
int trunc;
int openMode;
/* compute initial mode bits based on read-only flag in attributes */
initialModeBits = 0666;
- if (attributes & 1) initialModeBits &= ~0222;
+ if (attributes & 1)
+ initialModeBits &= ~0222;
pathp = (char *) (&p->parmsp[14]);
if (smb_StoreAnsiFilenames)
/* copy out remainder of the parms */
parmSlot = 0;
- outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
+ outp->parmsp[parmSlot++] = fidp->fid;
if (extraInfo) {
- outp->parmsp[parmSlot] = /* attrs */ 0; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++; /* mod time */
- outp->parmsp[parmSlot] = 0; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++; /* len */
- outp->parmsp[parmSlot] = 0x7fff; parmSlot++;
- outp->parmsp[parmSlot] = openMode; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */
- outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */
+ outp->parmsp[parmSlot++] = 0; /* attrs */
+ outp->parmsp[parmSlot++] = 0; /* mod time */
+ outp->parmsp[parmSlot++] = 0;
+ outp->parmsp[parmSlot++] = 0; /* len */
+ outp->parmsp[parmSlot++] = 0x7fff;
+ outp->parmsp[parmSlot++] = openMode;
+ outp->parmsp[parmSlot++] = 0; /* file type 0 ==> normal file or dir */
+ outp->parmsp[parmSlot++] = 0; /* IPC junk */
}
/* and the final "always present" stuff */
- outp->parmsp[parmSlot] = /* openAction found existing file */ 1; parmSlot++;
+ outp->parmsp[parmSlot++] = 1; /* openAction found existing file */
/* next write out the "unique" ID */
- outp->parmsp[parmSlot] = 0x1234; parmSlot++;
- outp->parmsp[parmSlot] = 0x5678; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++;
+ outp->parmsp[parmSlot++] = 0x1234;
+ outp->parmsp[parmSlot++] = 0x5678;
+ outp->parmsp[parmSlot++] = 0;
if (returnEALength) {
- outp->parmsp[parmSlot] = 0; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++;
+ outp->parmsp[parmSlot++] = 0;
+ outp->parmsp[parmSlot++] = 0;
}
outp->totalData = 0;
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if (code == CM_ERROR_TIDIPC) {
- /* Attempt to use TID allocated for IPC. The client is
- probably trying to locate DCE RPC end points, which
- we don't support. */
+ /* 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");
+#ifndef DFS_SUPPORT
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
return CM_ERROR_NOSUCHPATH;
+#endif
}
dscp = NULL;
- code = cm_NameI(cm_rootSCachep, pathp,
+ code = cm_NameI(cm_data.rootSCachep, pathp,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
if (code != 0) {
- code = cm_NameI(cm_rootSCachep, spacep->data,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
cm_FreeSpace(spacep);
return code;
}
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ smb_FreeTran2Packet(outp);
+ if ( WANTS_DFS_PATHNAMES(p) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* otherwise, scp points to the parent directory. Do a lookup,
* and truncate the file if we find it, otherwise we create the
* file.
smb_FreeTran2Packet(outp);
return code;
}
- }
- else {
+ } else {
+#ifdef DFS_SUPPORT
+ if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ smb_FreeTran2Packet(outp);
+ if ( WANTS_DFS_PATHNAMES(p) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
+ /* macintosh is expensive to program for it */
cm_FreeSpace(spacep);
}
if (code == 0) {
code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
if (code) {
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
if (excl) {
/* oops, file shouldn't be there */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
else
openAction = 1; /* found existing file */
}
- else if (!(openFun & SMB_ATTR_DIRECTORY)) {
+ else if (!(openFun & 0x10)) {
/* don't create if not found */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
osi_assert(scp == NULL);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
}
/* we don't need this any longer */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
if (code) {
/* something went wrong creating or truncating the file */
- if (scp) cm_ReleaseSCache(scp);
+ if (scp)
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
return code;
code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
if (code == 0) {
/* we have a more accurate file to use (the
- * target of the symbolic link). Otherwise,
- * we'll just use the symlink anyway.
- */
+ * target of the symbolic link). Otherwise,
+ * we'll just use the symlink anyway.
+ */
osi_Log2(smb_logp, "symlink vp %x to vp %x",
scp, targetScp);
cm_ReleaseSCache(scp);
/* copy out remainder of the parms */
parmSlot = 0;
- outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
+ outp->parmsp[parmSlot++] = fidp->fid;
lock_ObtainMutex(&scp->mx);
if (extraInfo) {
- outp->parmsp[parmSlot] = smb_Attributes(scp); parmSlot++;
+ outp->parmsp[parmSlot++] = smb_Attributes(scp);
smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
- outp->parmsp[parmSlot] = (unsigned short)(dosTime & 0xffff); parmSlot++;
- outp->parmsp[parmSlot] = (unsigned short)((dosTime>>16) & 0xffff); parmSlot++;
- outp->parmsp[parmSlot] = (unsigned short) (scp->length.LowPart & 0xffff);
- parmSlot++;
- outp->parmsp[parmSlot] = (unsigned short) ((scp->length.LowPart >> 16) & 0xffff);
- parmSlot++;
- outp->parmsp[parmSlot] = openMode; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */
- outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */
+ outp->parmsp[parmSlot++] = (unsigned short)(dosTime & 0xffff);
+ outp->parmsp[parmSlot++] = (unsigned short)((dosTime>>16) & 0xffff);
+ outp->parmsp[parmSlot++] = (unsigned short) (scp->length.LowPart & 0xffff);
+ outp->parmsp[parmSlot++] = (unsigned short) ((scp->length.LowPart >> 16) & 0xffff);
+ outp->parmsp[parmSlot++] = openMode;
+ outp->parmsp[parmSlot++] = 0; /* file type 0 ==> normal file or dir */
+ outp->parmsp[parmSlot++] = 0; /* IPC junk */
}
/* and the final "always present" stuff */
- outp->parmsp[parmSlot] = openAction; parmSlot++;
+ outp->parmsp[parmSlot++] = openAction;
/* next write out the "unique" ID */
- outp->parmsp[parmSlot] = (unsigned short) (scp->fid.vnode & 0xffff); parmSlot++;
- outp->parmsp[parmSlot] = (unsigned short) (scp->fid.volume & 0xffff); parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++;
+ outp->parmsp[parmSlot++] = (unsigned short) (scp->fid.vnode & 0xffff);
+ outp->parmsp[parmSlot++] = (unsigned short) (scp->fid.volume & 0xffff);
+ outp->parmsp[parmSlot++] = 0;
if (returnEALength) {
- outp->parmsp[parmSlot] = 0; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++;
+ outp->parmsp[parmSlot++] = 0;
+ outp->parmsp[parmSlot++] = 0;
}
lock_ReleaseMutex(&scp->mx);
outp->totalData = 0; /* total # of data bytes */
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, userp, tidPathp,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold, userp, tidPathp,
reqp, &dscp);
cm_FreeSpace(spacep);
- if (code) return code;
+ if (code)
+ return code;
+
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ return CM_ERROR_PATH_NOT_COVERED;
+ }
+#endif /* DFS_SUPPORT */
if (!lastNamep) lastNamep = pathp;
else lastNamep++;
long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx)
{
smb_tran2Packet_t *outp;
- time_t dosTime;
+ afs_uint32 dosTime;
FILETIME ft;
unsigned short infoLevel;
int nbytesRequired;
/* Make sure that lastComp is not NULL */
if (lastComp) {
if (stricmp(lastComp, "\\desktop.ini") == 0) {
- code = cm_NameI(cm_rootSCachep, spacep->data,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data,
CM_FLAG_CASEFOLD
| CM_FLAG_DIRSEARCH
| CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
if (code == 0) {
- if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT
- && !dscp->mountRootFidp)
+#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);
}
/* now do namei and stat, and copy out the info */
- code = cm_NameI(cm_rootSCachep, (char *)(&p->parmsp[3]),
+ code = cm_NameI(cm_data.rootSCachep, (char *)(&p->parmsp[3]),
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
if (code) {
return 0;
}
+#ifdef DFS_SUPPORT
+ if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(p) )
+ code = CM_ERROR_PATH_NOT_COVERED;
+ else
+ code = CM_ERROR_BADSHARENAME;
+ smb_SendTran2Error(vcp, p, opx, code);
+ smb_FreeTran2Packet(outp);
+ return 0;
+ }
+#endif /* DFS_SUPPORT */
+
lock_ObtainMutex(&scp->mx);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) &&
lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
- smb_UnixTimeFromLargeSearchTime(&attr.clientModTime,
- &lastMod);
+ smb_UnixTimeFromLargeSearchTime(&attr.clientModTime, &lastMod);
fidp->flags |= SMB_FID_MTIMESETDONE;
}
return CM_ERROR_BADOP;
}
+struct smb_v2_referral {
+ USHORT ServerType;
+ USHORT ReferralFlags;
+ ULONG Proximity;
+ ULONG TimeToLive;
+ USHORT DfsPathOffset;
+ USHORT DfsAlternativePathOffset;
+ USHORT NetworkAddressOffset;
+};
+
long
-smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
+smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
{
/* This is a UNICODE only request (bit15 of Flags2) */
/* The TID must be IPC$ */
/* ServerType = 0; indicates the next server should be queried for the file */
/* ReferralFlags = 0x01; PathConsumed characters should be stripped */
/* Node = UnicodeString of UNC path of the next share name */
+#ifdef DFS_SUPPORT
+ long code = 0;
+ int maxReferralLevel = 0;
+ char requestFileName[1024] = "";
+ smb_tran2Packet_t *outp = 0;
+ cm_user_t *userp = 0;
+ cm_scache_t *scp;
+ cm_req_t req;
+ CPINFO CodePageInfo;
+ int i, nbnLen, reqLen;
+ int idx;
+
+ cm_InitReq(&req);
+
+ maxReferralLevel = p->parmsp[0];
+
+ GetCPInfo(CP_ACP, &CodePageInfo);
+ WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) &p->parmsp[1], -1,
+ requestFileName, 1024, NULL, NULL);
+
+ osi_Log2(smb_logp,"ReceiveTran2GetDfsReferral [%d][%s]",
+ maxReferralLevel, osi_LogSaveString(smb_logp, requestFileName));
+
+ nbnLen = strlen(cm_NetbiosName);
+ reqLen = strlen(requestFileName);
+
+ if (reqLen == nbnLen + 5 &&
+ requestFileName[0] == '\\' &&
+ !_strnicmp(cm_NetbiosName,&requestFileName[1],nbnLen) &&
+ requestFileName[nbnLen+1] == '\\' &&
+ !_strnicmp("all",&requestFileName[nbnLen+2],3))
+ {
+ USHORT * sp;
+ struct smb_v2_referral * v2ref;
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 2 * (reqLen + 8));
+
+ sp = (USHORT *)outp->datap;
+ idx = 0;
+ sp[idx++] = reqLen; /* path consumed */
+ sp[idx++] = 1; /* number of referrals */
+ sp[idx++] = 0x03; /* flags */
+#ifdef DFS_VERSION_1
+ sp[idx++] = 1; /* Version Number */
+ sp[idx++] = reqLen + 4; /* Referral Size */
+ sp[idx++] = 1; /* Type = SMB Server */
+ sp[idx++] = 0; /* Do not strip path consumed */
+ for ( i=0;i<=reqLen; i++ )
+ sp[i+idx] = requestFileName[i];
+#else /* DFS_VERSION_2 */
+ sp[idx++] = 2; /* Version Number */
+ sp[idx++] = sizeof(struct smb_v2_referral); /* Referral Size */
+ idx += (sizeof(struct smb_v2_referral) / 2);
+ v2ref = (struct smb_v2_referral *) &sp[5];
+ v2ref->ServerType = 1; /* SMB Server */
+ v2ref->ReferralFlags = 0x03;
+ v2ref->Proximity = 0; /* closest */
+ v2ref->TimeToLive = 3600; /* seconds */
+ v2ref->DfsPathOffset = idx * 2;
+ v2ref->DfsAlternativePathOffset = idx * 2;
+ v2ref->NetworkAddressOffset = 0;
+ for ( i=0;i<=reqLen; i++ )
+ sp[i+idx] = requestFileName[i];
+#endif
+ } else {
+ userp = smb_GetTran2User(vcp, p);
+ if (!userp) {
+ osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
+ code = CM_ERROR_BADSMB;
+ goto done;
+ }
+
+ /* not done yet */
+ code = CM_ERROR_NOSUCHPATH;
+ }
- osi_Log0(smb_logp,"ReceiveTran2GetDFSReferral - NOT_SUPPORTED");
+ done:
+ if (userp)
+ cm_ReleaseUser(userp);
+ if (code == 0)
+ smb_SendTran2Packet(vcp, outp, op);
+ else
+ smb_SendTran2Error(vcp, p, op, code);
+ if (outp)
+ smb_FreeTran2Packet(outp);
+
+ return 0;
+#else /* DFS_SUPPORT */
+ osi_Log0(smb_logp,"ReceiveTran2GetDfsReferral - NOT_SUPPORTED");
return CM_ERROR_BADOP;
+#endif /* DFS_SUPPORT */
}
long
cm_scache_t *scp;
cm_scache_t *targetScp; /* target if scp is a symlink */
char *dptr;
- time_t dosTime;
+ afs_uint32 dosTime;
FILETIME ft;
int shortTemp;
unsigned short attr;
/* Copy attributes */
lattr = smb_ExtAttributes(scp);
+ if (code == CM_ERROR_NOSUCHPATH && scp->fileType == CM_SCACHETYPE_SYMLINK) {
+ if (lattr == SMB_ATTR_NORMAL)
+ lattr = SMB_ATTR_DIRECTORY;
+ else
+ lattr |= SMB_ATTR_DIRECTORY;
+ }
/* merge in hidden (dot file) attribute */
- if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
- lattr |= SMB_ATTR_HIDDEN;
+ if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
+ if (lattr == SMB_ATTR_NORMAL)
+ lattr = SMB_ATTR_HIDDEN;
+ else
+ lattr |= SMB_ATTR_HIDDEN;
+ }
*((u_long *)dptr) = lattr;
dptr += 4;
- }
- else {
+ } else {
/* get dos time */
smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
/* finally copy out attributes as short */
attr = smb_Attributes(scp);
/* merge in hidden (dot file) attribute */
- if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
- attr |= SMB_ATTR_HIDDEN;
+ if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
+ if (lattr == SMB_ATTR_NORMAL)
+ lattr = SMB_ATTR_HIDDEN;
+ else
+ lattr |= SMB_ATTR_HIDDEN;
+ }
*dptr++ = attr & 0xff;
*dptr++ = (attr >> 8) & 0xff;
}
int attribute;
long nextCookie;
char *tp;
- long code = 0;
+ long code = 0, code2 = 0;
char *pathp;
cm_dirEntry_t *dep;
int maxCount;
osi_assert(p->opcode == 2);
/* find next; obtain basic parameters from request or open dir file */
dsp = smb_FindDirSearch(p->parmsp[0]);
- if (!dsp)
- return CM_ERROR_BADFD;
- attribute = dsp->attribute;
maxCount = p->parmsp[1];
infoLevel = p->parmsp[2];
+ nextCookie = p->parmsp[3] | (p->parmsp[4] << 16);
searchFlags = p->parmsp[5];
+ if (!dsp) {
+ osi_Log2(smb_logp, "T2 search dir bad search ID: id %d nextCookie 0x%x",
+ p->parmsp[0], nextCookie);
+ return CM_ERROR_BADFD;
+ }
+ attribute = dsp->attribute;
pathp = NULL;
- nextCookie = p->parmsp[3] | (p->parmsp[4] << 16);
maskp = dsp->mask;
starPattern = 1; /* assume, since required a Find Next */
}
"T2 search dir attr 0x%x, info level %d, max count %d, flags 0x%x",
attribute, infoLevel, maxCount, searchFlags);
- osi_Log2(smb_logp, "...T2 search op %d, nextCookie 0x%x",
- p->opcode, nextCookie);
+ osi_Log3(smb_logp, "...T2 search op %d, id %d, nextCookie 0x%x",
+ p->opcode, dsp->cookie, nextCookie);
if (infoLevel >= 0x101)
searchFlags &= ~4; /* no resume keys */
outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
maxReturnData);
- osi_Log1(smb_logp, "T2 receive search dir %s",
- osi_LogSaveString(smb_logp, pathp));
+ osi_Log2(smb_logp, "T2 receive search dir count %d [%s]",
+ maxCount, osi_LogSaveString(smb_logp, pathp));
/* bail out if request looks bad */
if (p->opcode == 1 && !pathp) {
return CM_ERROR_BADSMB;
}
- osi_Log2(smb_logp, "T2 dir search cookie 0x%x, connection %d",
- nextCookie, dsp->cookie);
+ osi_Log3(smb_logp, "T2 search dir id %d, nextCookie 0x%x, attr 0x%x",
+ dsp->cookie, nextCookie, attribute);
userp = smb_GetTran2User(vcp, p);
if (!userp) {
- osi_Log1(smb_logp, "T2 dir search unable to resolve user [%d]", p->uid);
+ osi_Log1(smb_logp, "T2 search dir unable to resolve user [%d]", p->uid);
smb_ReleaseDirSearch(dsp);
smb_FreeTran2Packet(outp);
return CM_ERROR_BADSMB;
scp = dsp->scp;
cm_HoldSCache(scp);
code = 0;
- }
- else {
+ } else {
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->data, NULL, pathp);
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
smb_ReleaseDirSearch(dsp);
return 0;
}
- code = cm_NameI(cm_rootSCachep, spacep->data,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
cm_FreeSpace(spacep);
if (code == 0) {
- if (dsp->scp != 0)
- cm_ReleaseSCache(dsp->scp);
+#ifdef DFS_SUPPORT_BUT_NOT_FIND_FIRST
+ if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(p) )
+ code = CM_ERROR_PATH_NOT_COVERED;
+ else
+ code = CM_ERROR_BADSHARENAME;
+ smb_SendTran2Error(vcp, p, opx, code);
+ smb_FreeTran2Packet(outp);
+ lock_ReleaseMutex(&dsp->mx);
+ smb_DeleteDirSearch(dsp);
+ smb_ReleaseDirSearch(dsp);
+ return 0;
+ }
+#endif /* DFS_SUPPORT */
dsp->scp = scp;
/* we need one hold for the entry we just stored into,
* and one for our own processing. When we're done
dsp->flags |= SMB_DIRSEARCH_BULKST;
}
lock_ReleaseMutex(&scp->mx);
- }
+ }
}
lock_ReleaseMutex(&dsp->mx);
if (code) {
/* check if we've passed the dir's EOF */
if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
+ osi_Log0(smb_logp, "T2 search dir passed eof");
eos = 1;
break;
}
* the dir entry, since we'll need to check its size.
*/
if (returnedNames >= maxCount) {
+ osi_Log2(smb_logp, "T2 search dir returnedNames %d >= maxCount %d",
+ returnedNames, maxCount);
break;
}
* the offset of the buffer we have. If not, get the buffer.
*/
thyper.HighPart = curOffset.HighPart;
- thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
+ thyper.LowPart = curOffset.LowPart & ~(cm_data.buf_blockSize-1);
if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
/* wrong buffer */
if (bufferp) {
lock_ObtainMutex(&scp->mx);
}
lock_ReleaseMutex(&dsp->mx);
- if (code)
+ if (code) {
+ osi_Log2(smb_logp, "T2 search dir buf_Get scp %x failed %d", scp, code);
break;
+ }
bufferOffset = thyper;
PRSFS_LOOKUP,
CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_READ);
- if (code) break;
+ if (code) {
+ osi_Log2(smb_logp, "T2 search dir cm_SyncOp scp %x failed %d", scp, code);
+ break;
+ }
- if (cm_HaveBuffer(scp, bufferp, 0)) break;
+ if (cm_HaveBuffer(scp, bufferp, 0)) {
+ osi_Log2(smb_logp, "T2 search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
+ break;
+ }
/* otherwise, load the buffer and try again */
code = cm_GetBuffer(scp, bufferp, NULL, userp,
&req);
- if (code) break;
+ if (code) {
+ osi_Log3(smb_logp, "T2 search dir cm_GetBuffer failed scp %x bufferp %x code %d",
+ scp, bufferp, code);
+ break;
+ }
}
if (code) {
buf_Release(bufferp);
* in; copy it out if it represents a non-deleted entry.
*/
entryInDir = curOffset.LowPart & (2048-1);
- entryInBuffer = curOffset.LowPart & (buf_bufferSize - 1);
+ entryInBuffer = curOffset.LowPart & (cm_data.buf_blockSize - 1);
/* page header will help tell us which entries are free. Page
* header can change more often than once per buffer, since
* a buffer package buffer.
*/
/* only look intra-buffer */
- temp = curOffset.LowPart & (buf_bufferSize - 1);
+ temp = curOffset.LowPart & (cm_data.buf_blockSize - 1);
temp &= ~(2048 - 1); /* turn off intra-page bits */
pageHeaderp = (cm_pageHeader_t *) (bufferp->datap + temp);
NeedShortName = 1;
}
+ osi_Log3(smb_logp, "T2 search dir vn %u name %s (%s)",
+ dep->fid.vnode, osi_LogSaveString(smb_logp, dep->name),
+ NeedShortName ? osi_LogSaveString(smb_logp, shortName) : "");
+
/* When matching, we are using doing a case fold if we have a wildcard mask.
* If we get a non-wildcard match, it's a lookup for a specific file.
*/
/* Eliminate entries that don't match requested attributes */
if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) &&
- smb_IsDotFile(dep->name))
+ smb_IsDotFile(dep->name)) {
+ osi_Log0(smb_logp, "T2 search dir skipping hidden");
goto nextEntry; /* no hidden files */
-
+ }
if (!(dsp->attribute & SMB_ATTR_DIRECTORY)) /* no directories */
{
/* We have already done the cm_TryBulkStat above */
/*osi_Log2(smb_logp, "smb_ReceiveTran2SearchDir: file %s "
"has filetype %d", dep->name,
fileType);*/
- if (fileType == CM_SCACHETYPE_DIRECTORY)
+ if (fileType == CM_SCACHETYPE_DIRECTORY ||
+ fileType == CM_SCACHETYPE_DFSLINK ||
+ fileType == CM_SCACHETYPE_INVALID)
+ osi_Log0(smb_logp, "T2 search dir skipping directory or bad link");
goto nextEntry;
}
align = (4 - (orbytes & 3)) & 3;
else
align = 0;
- if (orbytes + bytesInBuffer + align > maxReturnData)
+ if (orbytes + bytesInBuffer + align > maxReturnData) {
+ osi_Log1(smb_logp, "T2 dir search exceed max return data %d",
+ maxReturnData);
break;
+ }
/* this is one of the entries to use: it is not deleted
* and it matches the star pattern we're looking for.
bytesInBuffer++;
}
} /* if we're including this name */
- else if (!NeedShortName &&
- !starPattern &&
+ else if (!starPattern &&
!foundInexact &&
dep->fid.vnode != 0 &&
smb_V3MatchMask(dep->name, maskp, CM_FLAG_CASEFOLD)) {
/* release the mutex */
lock_ReleaseMutex(&scp->mx);
- if (bufferp) buf_Release(bufferp);
+ if (bufferp)
+ buf_Release(bufferp);
/* apply and free last set of patches; if not doing a star match, this
* will be empty, but better safe (and freeing everything) than sorry.
*/
- smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp,
+ code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp,
&req);
/* now put out the final parameters */
- if (returnedNames == 0) eos = 1;
+ if (returnedNames == 0)
+ eos = 1;
if (p->opcode == 1) {
/* find first */
outp->parmsp[0] = (unsigned short) dsp->cookie;
/* return # of bytes in the buffer */
outp->totalData = bytesInBuffer;
- osi_Log2(smb_logp, "T2 search dir done, %d names, code %d",
- returnedNames, code);
-
/* Return error code if unsuccessful on first request */
if (code == 0 && p->opcode == 1 && returnedNames == 0)
code = CM_ERROR_NOSUCHFILE;
+ osi_Log4(smb_logp, "T2 search dir done, opcode %d, id %d, %d names, code %d",
+ p->opcode, dsp->cookie, returnedNames, code);
+
/* if we're supposed to close the search after this request, or if
* we're supposed to close the search if we're done, and we're done,
* or if something went wrong, close the search.
smb_DeleteDirSearch(dsp);
if (code)
smb_SendTran2Error(vcp, p, opx, code);
- else {
+ else
smb_SendTran2Packet(vcp, outp, opx);
- }
+
smb_FreeTran2Packet(outp);
smb_ReleaseDirSearch(dsp);
cm_ReleaseSCache(scp);
smb_fid_t *fidp;
int attributes;
char *lastNamep;
- time_t dosTime;
+ afs_uint32 dosTime;
int openFun;
int trunc;
int openMode;
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_rootSCachep, pathp,
+ code = cm_NameI(cm_data.rootSCachep, pathp,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
+
+#ifdef DFS_SUPPORT
+ if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
if (code != 0) {
- code = cm_NameI(cm_rootSCachep, spacep->data,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
-
if (code) {
cm_ReleaseUser(userp);
return code;
}
-
+
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* otherwise, scp points to the parent directory. Do a lookup,
* and truncate the file if we find it, otherwise we create the
* file.
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
&req, &scp);
if (code && code != CM_ERROR_NOSUCHFILE) {
- cm_ReleaseSCache(dscp);
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
return code;
}
if (code == 0) {
code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
if (code) {
- if (dscp)
- cm_ReleaseSCache(dscp);
+ if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
return code;
}
else openAction = 1; /* found existing file */
}
- else if (!(openFun & 0x10)) {
+ else if (!(openFun & SMB_ATTR_DIRECTORY)) {
/* don't create if not found */
if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
}
/* we don't need this any longer */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
if (code) {
/* something went wrong creating or truncating the file */
- if (scp) cm_ReleaseSCache(scp);
+ if (scp)
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
return code;
}
fidp->scp = scp;
/* compute open mode */
- if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
+ if (openMode != 1)
+ fidp->flags |= SMB_FID_OPENREAD;
if (openMode == 1 || openMode == 2)
fidp->flags |= SMB_FID_OPENWRITE;
return 0;
}
+/* The file locking code is incomplete and that which is implemented in cm_Lock()
+ * is broken. What exists functions only because it is rarely if ever called.
+ * The tests activated by FULL_LOCKS_ONLY ensure that cm_Lock() is only called
+ * if the lock covers the entire file. Therefore, RXAFS_SetLock is only called
+ * rarely. That means that AFS locks are ignored by Windows clients.
+ * When cm_Lock is re-written, undefine or better yet remove, the FULL_LOCKS_ONLY
+ * code.
+ */
+#define FULL_LOCKS_ONLY
long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
cm_req_t req;
fidp = smb_FindFID(vcp, fid, 0);
if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+ osi_Log0(smb_logp, "smb_ReceiveV3Locking BadFD");
return CM_ERROR_BADFD;
}
/* set inp->fid so that later read calls in same msg can find fid */
CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_GETSTATUS
| CM_SCACHESYNC_LOCK);
- if (code)
- goto doneSync;
-
- LockType = smb_GetSMBParm(inp, 3) & 0xff;
- Timeout = (smb_GetSMBParm(inp, 5) << 16) + smb_GetSMBParm(inp, 4);
- NumberOfUnlocks = smb_GetSMBParm(inp, 6);
- NumberOfLocks = smb_GetSMBParm(inp, 7);
-
- op = smb_GetSMBData(inp, NULL);
-
- for (i=0; i<NumberOfUnlocks; i++) {
- if (LockType & 0x10) {
- /* Large Files */
- LOffset.HighPart = *((LONG *)(op + 4));
- LOffset.LowPart = *((DWORD *)(op + 8));
- LLength.HighPart = *((LONG *)(op + 12));
- LLength.LowPart = *((DWORD *)(op + 16));
- op += 20;
- }
- else {
- /* Not Large Files */
- LOffset.HighPart = 0;
- LOffset.LowPart = *((DWORD *)(op + 2));
- LLength.HighPart = 0;
- LLength.LowPart = *((DWORD *)(op + 6));
- op += 10;
- }
- if (LargeIntegerNotEqualToZero(LOffset))
- continue;
- /* Do not check length -- length check done in cm_Unlock */
-
- code = cm_Unlock(scp, LockType, LOffset, LLength, userp, &req);
- if (code) goto done;
- }
-
- for (i=0; i<NumberOfLocks; i++) {
- if (LockType & 0x10) {
- /* Large Files */
- LOffset.HighPart = *((LONG *)(op + 4));
- LOffset.LowPart = *((DWORD *)(op + 8));
- LLength.HighPart = *((LONG *)(op + 12));
- LLength.LowPart = *((DWORD *)(op + 16));
- op += 20;
- }
- else {
- /* Not Large Files */
- LOffset.HighPart = 0;
- LOffset.LowPart = *((DWORD *)(op + 2));
- LLength.HighPart = 0;
- LLength.LowPart = *((DWORD *)(op + 6));
- op += 10;
- }
- if (LargeIntegerNotEqualToZero(LOffset))
- continue;
- if (LargeIntegerLessThan(LOffset, scp->length))
- continue;
+ if (code) {
+ osi_Log1(smb_logp, "smb_ReceiveV3Locking SyncOp failure code 0x%x", code);
+ goto doneSync;
+ }
- code = cm_Lock(scp, LockType, LOffset, LLength, Timeout,
- userp, &req, &lockp);
- if (code == CM_ERROR_WOULDBLOCK && Timeout != 0) {
- /* Put on waiting list */
- waitingLock = malloc(sizeof(smb_waitingLock_t));
- waitingLock->vcp = vcp;
- smb_HoldVC(vcp);
- waitingLock->inp = smb_CopyPacket(inp);
- waitingLock->outp = smb_CopyPacket(outp);
- waitingLock->timeRemaining = Timeout;
- waitingLock->lockp = lockp;
- lock_ObtainWrite(&smb_globalLock);
- osi_QAdd((osi_queue_t **)&smb_allWaitingLocks,
- &waitingLock->q);
- osi_Wakeup((long) &smb_allWaitingLocks);
- lock_ReleaseWrite(&smb_globalLock);
- /* don't send reply immediately */
- outp->flags |= SMB_PACKETFLAG_NOSEND;
- }
- if (code)
- break;
- }
+ LockType = smb_GetSMBParm(inp, 3) & 0xff;
+ Timeout = (smb_GetSMBParm(inp, 5) << 16) + smb_GetSMBParm(inp, 4);
+ NumberOfUnlocks = smb_GetSMBParm(inp, 6);
+ NumberOfLocks = smb_GetSMBParm(inp, 7);
+
+ op = smb_GetSMBData(inp, NULL);
+
+ for (i=0; i<NumberOfUnlocks; i++) {
+ if (LockType & LOCKING_ANDX_LARGE_FILES) {
+ /* Large Files */
+ LOffset.HighPart = *((LONG *)(op + 4));
+ LOffset.LowPart = *((DWORD *)(op + 8));
+ LLength.HighPart = *((LONG *)(op + 12));
+ LLength.LowPart = *((DWORD *)(op + 16));
+ op += 20;
+ }
+ else {
+ /* Not Large Files */
+ LOffset.HighPart = 0;
+ LOffset.LowPart = *((DWORD *)(op + 2));
+ LLength.HighPart = 0;
+ LLength.LowPart = *((DWORD *)(op + 6));
+ op += 10;
+ }
+#ifdef FULL_LOCKS_ONLY
+ if (LargeIntegerNotEqualToZero(LOffset)) {
+ osi_Log2(smb_logp, "smb_ReceiveV3Locking Unlock %d offset 0x%x != Zero",
+ i, (long)LOffset.QuadPart);
+ continue;
+ }
+#endif /* FULL_LOCKS_ONLY */
+ /* Do not check length -- length check done in cm_Unlock */
+
+ code = cm_Unlock(scp, LockType, LOffset, LLength, userp, &req);
+ if (code) goto done;
+ }
+
+ for (i=0; i<NumberOfLocks; i++) {
+ if (LockType & LOCKING_ANDX_LARGE_FILES) {
+ /* Large Files */
+ LOffset.HighPart = *((LONG *)(op + 4));
+ LOffset.LowPart = *((DWORD *)(op + 8));
+ LLength.HighPart = *((LONG *)(op + 12));
+ LLength.LowPart = *((DWORD *)(op + 16));
+ op += 20;
+ }
+ else {
+ /* Not Large Files */
+ LOffset.HighPart = 0;
+ LOffset.LowPart = *((DWORD *)(op + 2));
+ LLength.HighPart = 0;
+ LLength.LowPart = *((DWORD *)(op + 6));
+ op += 10;
+ }
+#ifdef FULL_LOCKS_ONLY
+ if (LargeIntegerNotEqualToZero(LOffset)) {
+ osi_Log2(smb_logp, "smb_ReceiveV3Locking Lock %d offset 0x%x != Zero",
+ i, (long)LOffset.QuadPart);
+ continue;
+ }
+ if (LargeIntegerLessThan(LOffset, scp->length)) {
+ osi_Log3(smb_logp, "smb_ReceiveV3Locking Unlock %d offset 0x%x < 0x%x",
+ i, (long)LOffset.QuadPart, (long)scp->length.QuadPart);
+ continue;
+ }
+#endif /* FULL_LOCKS_ONLY */
+ code = cm_Lock(scp, LockType, LOffset, LLength, Timeout,
+ userp, &req, &lockp);
+ if (code == CM_ERROR_WOULDBLOCK && Timeout != 0) {
+ /* Put on waiting list */
+ waitingLock = malloc(sizeof(smb_waitingLock_t));
+ waitingLock->vcp = vcp;
+ smb_HoldVC(vcp);
+ waitingLock->inp = smb_CopyPacket(inp);
+ waitingLock->outp = smb_CopyPacket(outp);
+ waitingLock->timeRemaining = Timeout;
+ waitingLock->lockp = lockp;
+ lock_ObtainWrite(&smb_globalLock);
+ osi_QAdd((osi_queue_t **)&smb_allWaitingLocks,
+ &waitingLock->q);
+ osi_Wakeup((long) &smb_allWaitingLocks);
+ lock_ReleaseWrite(&smb_globalLock);
+ /* don't send reply immediately */
+ outp->flags |= SMB_PACKETFLAG_NOSEND;
+ osi_Log1(smb_logp, "smb_ReceiveV3Locking WaitingLock created 0x%x",
+ (long) waitingLock);
+ continue;
+ }
+ if (code) {
+ osi_Log1(smb_logp, "smb_ReceiveV3Locking cm_Lock failure code 0x%x", code);
+ break;
+ }
+ }
if (code) {
/* release any locks acquired before the failure */
+ osi_Log0(smb_logp, "smb_ReceiveV3Locking - failure; should be releasing locks but don't!!!!");
}
else
smb_SetSMBDataLength(outp, 0);
smb_fid_t *fidp;
cm_scache_t *scp;
long code = 0;
- time_t searchTime;
+ afs_uint32 searchTime;
cm_user_t *userp;
cm_req_t req;
smb_fid_t *fidp;
cm_scache_t *scp;
long code = 0;
- time_t searchTime;
+ afs_uint32 searchTime;
time_t unixTime;
cm_user_t *userp;
cm_attr_t attrs;
#define FILE_OVERWRITE 4 // (open & truncate, but do not create)
#define FILE_OVERWRITE_IF 5 // (open & truncate, or create)
+/* Flags field */
+#define REQUEST_OPLOCK 2
+#define REQUEST_BATCH_OPLOCK 4
+#define OPEN_DIRECTORY 8
+#define EXTENDED_RESPONSE_REQUIRED 0x10
+
+/* CreateOptions field. */
+#define FILE_DIRECTORY_FILE 0x0001
+#define FILE_WRITE_THROUGH 0x0002
+#define FILE_SEQUENTIAL_ONLY 0x0004
+#define FILE_NON_DIRECTORY_FILE 0x0040
+#define FILE_NO_EA_KNOWLEDGE 0x0200
+#define FILE_EIGHT_DOT_THREE_ONLY 0x0400
+#define FILE_RANDOM_ACCESS 0x0800
+#define FILE_DELETE_ON_CLOSE 0x1000
+#define FILE_OPEN_BY_FILE_ID 0x2000
+
long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
char *pathp, *realPathp;
unsigned int requestOpLock;
unsigned int requestBatchOpLock;
unsigned int mustBeDir;
+ unsigned int extendedRespRequired;
unsigned int treeCreate;
int realDirFlag;
unsigned int desiredAccess;
nameLength = smb_GetSMBOffsetParm(inp, 2, 1);
flags = smb_GetSMBOffsetParm(inp, 3, 1)
| (smb_GetSMBOffsetParm(inp, 4, 1) << 16);
- requestOpLock = flags & 0x02;
- requestBatchOpLock = flags & 0x04;
- mustBeDir = flags & 0x08;
+ requestOpLock = flags & REQUEST_OPLOCK;
+ requestBatchOpLock = flags & REQUEST_BATCH_OPLOCK;
+ mustBeDir = flags & OPEN_DIRECTORY;
+ extendedRespRequired = flags & EXTENDED_RESPONSE_REQUIRED;
/*
* Why all of a sudden 32-bit FID?
/* mustBeDir is never set; createOptions directory bit seems to be
* more important
*/
- if (createOptions & 1)
+ if (createOptions & FILE_DIRECTORY_FILE)
realDirFlag = 1;
- else if (createOptions & 0x40)
+ else if (createOptions & FILE_NON_DIRECTORY_FILE)
realDirFlag = 0;
else
realDirFlag = -1;
}
if (baseFid == 0) {
- baseDirp = cm_rootSCachep;
+ baseDirp = cm_data.rootSCachep;
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->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. */
+ * don't support OR it could be looking to make a DFS
+ * referral request.
+ */
osi_Log0(smb_logp, "NTCreateX received IPC TID");
+#ifndef DFS_SUPPORT
free(realPathp);
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHFILE;
+#endif /* DFS_SUPPORT */
}
- }
- else {
+ } else {
baseFidp = smb_FindFID(vcp, baseFid, 0);
if (!baseFidp) {
osi_Log1(smb_logp, "NTCreateX Invalid base fid [%d]", baseFid);
fidflags |= SMB_FID_OPENREAD;
if (desiredAccess & AFS_ACCESS_WRITE)
fidflags |= SMB_FID_OPENWRITE;
+ if (createOptions & FILE_DELETE_ON_CLOSE)
+ fidflags |= SMB_FID_DELONCLOSE;
code = 0;
code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
if (code == 0) {
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
userp, &req, &scp);
if (code == CM_ERROR_NOSUCHFILE) {
} else {
code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
+#ifdef DFS_SUPPORT
+ if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
/* we might have scp but not dscp */
}
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
+#ifdef DFS_SUPPORT
+ if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ if (scp)
+ cm_ReleaseSCache(scp);
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
if (code &&
(tp = strrchr(spacep->data,'\\')) &&
(createDisp == FILE_CREATE) &&
}
} while (dscp == NULL && code == 0);
} else
- code = 0;
+ code = 0;
/* we might have scp and we might have dscp */
if (!smb_IsLegalFilename(lastNamep)) {
if (scp)
cm_ReleaseSCache(scp);
- if (dscp)
- cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_BADNTFILENAME;
userp, &req, &scp);
}
if (code && code != CM_ERROR_NOSUCHFILE) {
- cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
/* oops, file shouldn't be there */
if (dscp)
cm_ReleaseSCache(dscp);
- cm_ReleaseSCache(scp);
+ if (scp)
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_EXISTS;
if (code) {
if (dscp)
cm_ReleaseSCache(dscp);
- cm_ReleaseSCache(scp);
+ if (scp)
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
return 0;
}
-
/*
* A lot of stuff copied verbatim from NT Create&X to NT Tran Create.
* Instead, ultimately, would like to use a subroutine for common code.
lparmp = (ULONG *) parmp;
flags = lparmp[0];
- requestOpLock = flags & 0x02;
- requestBatchOpLock = flags & 0x04;
- mustBeDir = flags & 0x08;
- extendedRespRequired = flags & 0x10;
+ requestOpLock = flags & REQUEST_OPLOCK;
+ requestBatchOpLock = flags & REQUEST_BATCH_OPLOCK;
+ mustBeDir = flags & OPEN_DIRECTORY;
+ extendedRespRequired = flags & EXTENDED_RESPONSE_REQUIRED;
/*
* Why all of a sudden 32-bit FID?
/* mustBeDir is never set; createOptions directory bit seems to be
* more important
*/
- if (createOptions & 1)
+ if (createOptions & FILE_DIRECTORY_FILE)
realDirFlag = 1;
- else if (createOptions & 0x40)
+ else if (createOptions & FILE_NON_DIRECTORY_FILE)
realDirFlag = 0;
else
realDirFlag = -1;
}
if (baseFid == 0) {
- baseDirp = cm_rootSCachep;
+ baseDirp = cm_data.rootSCachep;
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
- if(code == CM_ERROR_TIDIPC) {
- /* Attempt to use TID allocated for IPC. The client is
- * probably trying to locate DCE RPC endpoints, which we
- * don't support. */
+ 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, "NTTranCreate received IPC TID");
+#ifndef DFS_SUPPORT
free(realPathp);
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
+#endif
}
- }
- else {
+ } else {
baseFidp = smb_FindFID(vcp, baseFid, 0);
if (!baseFidp) {
osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
fidflags |= SMB_FID_OPENREAD;
if (desiredAccess & AFS_ACCESS_WRITE)
fidflags |= SMB_FID_OPENWRITE;
+ if (createOptions & FILE_DELETE_ON_CLOSE)
+ fidflags |= SMB_FID_DELONCLOSE;
dscp = NULL;
code = 0;
code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
if (code == 0) {
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
userp, &req, &scp);
if (code == CM_ERROR_NOSUCHFILE) {
} else {
code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
+#ifdef DFS_SUPPORT
+ if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
}
if (code == 0)
foundscp = TRUE;
- if (code != 0
- || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
+
+ if (code != 0 || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
/* look up parent directory */
if ( !dscp ) {
code = cm_NameI(baseDirp, spacep->data,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
+#ifdef DFS_SUPPORT
+ if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
} else
code = 0;
return code;
}
}
- }
- else {
+ } else {
if (baseFid != 0) {
smb_ReleaseFID(baseFidp);
baseFidp = 0;
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
&req);
if (code) {
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
}
else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
/* don't create if not found */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_NOSUCHFILE;
}
} /* lookup succeeded */
}
- }
- else {
+ } else {
/* create directory */
osi_assert(dscp != NULL);
osi_Log1(smb_logp,
if (code) {
/* something went wrong creating or truncating the file */
- if (scp) cm_ReleaseSCache(scp);
+ if (scp)
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
fidp->NTopen_wholepathp = realPathp;
/* we don't need this any longer */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_Open(scp, 0, userp);
lock_ReleaseMutex(&dscp->mx);
/* Convert to response packet */
- ((smb_t *) watch)->reb = 0x80;
+ ((smb_t *) watch)->reb = SMB_FLAGS_SERVER_TO_CLIENT | SMB_FLAGS_CANONICAL_PATHNAMES;
((smb_t *) watch)->wct = 0;
/* out parms */
((smb_t *) watch)->errLow = 0;
((smb_t *) watch)->errHigh = 0;
/* Set NT Status codes flag */
- ((smb_t *) watch)->flg2 |= SMB_FLAGS2_ERR_STATUS;
+ ((smb_t *) watch)->flg2 |= SMB_FLAGS2_32BIT_STATUS;
}
smb_SendPacket(vcp, watch);
((smb_t *)watch)->reh = 0x1;
((smb_t *)watch)->errLow = 0;
((smb_t *)watch)->errHigh = 0xC0;
- ((smb_t *)watch)->flg2 |= SMB_FLAGS2_ERR_STATUS;
+ ((smb_t *)watch)->flg2 |= SMB_FLAGS2_32BIT_STATUS;
smb_SendPacket(vcp, watch);
smb_FreePacket(watch);
return 0;
lock_ObtainMutex(&unp->mx);
unp->userp = cm_NewUser();
lock_ReleaseMutex(&unp->mx);
- osi_Log2(smb_logp,"smb_FindCMUserByName New user name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
+ osi_Log2(smb_logp,"smb_FindCMUserByName New user name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
osi_LogEvent("AFS smb_FindCMUserByName : New User",NULL,"name[%s] machine[%s]",usern,machine);
} else {
osi_Log2(smb_logp,"smb_FindCMUserByName Not found name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));