#include <ntstatus.h>
#define SECURITY_WIN32
#include <security.h>
+#include <sddl.h>
#include <lmaccess.h>
#pragma warning(pop)
#include <stdlib.h>
* turns out to be impolitic in NT. See defect 10007.
*/
#ifdef notdef
- if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+ if ((scp->unixModeBits & 0200) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
attrs |= SMB_ATTR_READONLY; /* Read-only */
#else
- if ((scp->unixModeBits & 0222) == 0)
+ if ((scp->unixModeBits & 0200) == 0)
attrs |= SMB_ATTR_READONLY; /* Read-only */
#endif
return;
}
+afs_uint32
+smb_GetLogonSID(HANDLE hToken, PSID *ppsid)
+{
+ BOOL bSuccess = FALSE;
+ DWORD dwIndex;
+ DWORD dwLength = 0;
+ PTOKEN_GROUPS ptg = NULL;
+
+ // Verify the parameter passed in is not NULL.
+ if (NULL == ppsid)
+ goto Cleanup;
+
+ // Get required buffer size and allocate the TOKEN_GROUPS buffer.
+
+ if (!GetTokenInformation( hToken, // handle to the access token
+ TokenGroups, // get information about the token's groups
+ (LPVOID) ptg, // pointer to TOKEN_GROUPS buffer
+ 0, // size of buffer
+ &dwLength // receives required buffer size
+ ))
+ {
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ goto Cleanup;
+
+ ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY, dwLength);
+
+ if (ptg == NULL)
+ goto Cleanup;
+ }
+
+ // Get the token group information from the access token.
+
+ if (!GetTokenInformation( hToken, // handle to the access token
+ TokenGroups, // get information about the token's groups
+ (LPVOID) ptg, // pointer to TOKEN_GROUPS buffer
+ dwLength, // size of buffer
+ &dwLength // receives required buffer size
+ ))
+ {
+ goto Cleanup;
+ }
+
+ // Loop through the groups to find the logon SID.
+ for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) {
+ if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
+ {
+ // Found the logon SID; make a copy of it.
+
+ dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid);
+ *ppsid = (PSID) HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY, dwLength);
+ if (*ppsid == NULL)
+ goto Cleanup;
+ if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid))
+ {
+ HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
+ goto Cleanup;
+ }
+ bSuccess = TRUE;
+ break;
+ }
+ }
+
+ Cleanup:
+
+ // Free the buffer for the token groups.
+ if (ptg != NULL)
+ HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
+
+ return bSuccess;
+}
+
+afs_uint32
+smb_GetUserSID(HANDLE hToken, PSID *ppsid)
+{
+ BOOL bSuccess = FALSE;
+ DWORD dwLength = 0;
+ PTOKEN_USER ptu = NULL;
+
+ // Verify the parameter passed in is not NULL.
+ if (NULL == ppsid)
+ goto Cleanup;
+
+ // Get required buffer size and allocate the TOKEN_USER buffer.
+
+ if (!GetTokenInformation( hToken, // handle to the access token
+ TokenUser, // get information about the token's user
+ (LPVOID) ptu, // pointer to TOKEN_USER buffer
+ 0, // size of buffer
+ &dwLength // receives required buffer size
+ ))
+ {
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ goto Cleanup;
+
+ ptu = (PTOKEN_USER)HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY, dwLength);
+
+ if (ptu == NULL)
+ goto Cleanup;
+ }
+
+ // Get the token group information from the access token.
+
+ if (!GetTokenInformation( hToken, // handle to the access token
+ TokenUser, // get information about the token's user
+ (LPVOID) ptu, // pointer to TOKEN_USER buffer
+ dwLength, // size of buffer
+ &dwLength // receives required buffer size
+ ))
+ {
+ goto Cleanup;
+ }
+
+ // Found the user SID; make a copy of it.
+ dwLength = GetLengthSid(ptu->User.Sid);
+ *ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
+ if (*ppsid == NULL)
+ goto Cleanup;
+ if (!CopySid(dwLength, *ppsid, ptu->User.Sid))
+ {
+ HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
+ goto Cleanup;
+ }
+ bSuccess = TRUE;
+
+ Cleanup:
+
+ // Free the buffer for the token groups.
+ if (ptu != NULL)
+ HeapFree(GetProcessHeap(), 0, (LPVOID)ptu);
+
+ return bSuccess;
+}
+
+void
+smb_FreeSID (PSID psid)
+{
+ HeapFree(GetProcessHeap(), 0, (LPVOID)psid);
+}
+
+
struct smb_ext_context {
CredHandle creds;
CtxtHandle ctx;
long smb_AuthenticateUserExt(smb_vc_t * vcp, clientchar_t * usern,
char * secBlobIn, int secBlobInLength,
- char ** secBlobOut, int * secBlobOutLength) {
+ char ** secBlobOut, int * secBlobOutLength,
+ wchar_t **secSidString) {
SECURITY_STATUS status, istatus;
CredHandle creds;
TimeStamp expiry;
*secBlobOut = NULL;
*secBlobOutLength = 0;
+ *secSidString = NULL;
if (vcp->flags & SMB_VCFLAG_AUTH_IN_PROGRESS) {
secCtx = vcp->secCtx;
if (status == SEC_E_OK || status == SEC_I_COMPLETE_NEEDED) {
/* woo hoo! */
+ HANDLE hToken = 0;
SecPkgContext_NamesW names;
OutputDebugF(_C("Authentication completed"));
OutputDebugF(_C("QueryContextAttributes Names failed [%x]"), GetLastError());
code = CM_ERROR_BADPASSWORD;
}
+
+ /* Obtain the user's SID */
+ if (code == 0 && !QuerySecurityContextToken(((secCtx)?&ctx:NULL), &hToken)) {
+ PSID pSid = 0;
+ OutputDebugF(_C("Received hToken"));
+
+ if (smb_GetUserSID(hToken, &pSid))
+ ConvertSidToStringSidW(pSid, secSidString);
+
+ if (pSid)
+ smb_FreeSID(pSid);
+ CloseHandle(hToken);
+ } else {
+ OutputDebugF(_C("QueryContextToken failed [%x]"), GetLastError());
+ }
} else if (!code) {
switch ( status ) {
case SEC_E_INVALID_TOKEN:
clientchar_t *s1 = _C(" ");
long code = 0;
clientchar_t usern[SMB_MAX_USERNAME_LENGTH];
+ int usernIsSID = 0;
char *secBlobOut = NULL;
int secBlobOutLength = 0;
+ wchar_t *secSidString = 0;
int maxBufferSize = 0;
int maxMpxCount = 0;
int vcNumber = 0;
secBlobInLength = smb_GetSMBParm(inp, 7);
secBlobIn = smb_GetSMBData(inp, NULL);
- code = smb_AuthenticateUserExt(vcp, usern, secBlobIn, secBlobInLength, &secBlobOut, &secBlobOutLength);
+ code = smb_AuthenticateUserExt(vcp, usern, secBlobIn, secBlobInLength, &secBlobOut, &secBlobOutLength, &secSidString);
if (code == CM_ERROR_GSSCONTINUE) {
size_t cb_data = 0;
early to avoid accidently stealing someone else's tokens. */
if (code) {
+ if (secSidString)
+ LocalFree(secSidString);
return code;
}
+ /*
+ * If the SidString for the user could be obtained, use that
+ * for the user id
+ */
+ if (secSidString) {
+ cm_ClientStrCpy(usern, SMB_MAX_USERNAME_LENGTH, secSidString);
+ usernIsSID = 1;
+ }
+
OutputDebugF(_C("Received username=[%s]"), usern);
/* On Windows 2000, this function appears to be called more often than
*/
unp->flags &= ~SMB_USERNAMEFLAG_AFSLOGON;
}
+ if (usernIsSID)
+ unp->flags |= SMB_USERNAMEFLAG_SID;
lock_ReleaseMutex(&unp->mx);
/* Create a new UID and cm_user_t structure */
}
}
+ if (secSidString)
+ LocalFree(secSidString);
return 0;
}
osi_Log2(smb_logp, "smb_nmpipeSetState for fd[%d] with state[0x%x]", fd, pipeState);
fidp = smb_FindFID(vcp, fd, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_nmpipeSetState Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
return CM_ERROR_BADFD;
-
+ }
lock_ObtainMutex(&fidp->mx);
if (pipeState & 0x8000)
fidp->flags |= SMB_FID_BLOCKINGPIPE;
fd, p->totalData, p->maxReturnData);
fidp = smb_FindFID(vcp, fd, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_nmpipeTransact Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
return CM_ERROR_BADFD;
-
+ }
lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_RPC) {
is_rpc = 1;
smb_ReleaseFID(fidp);
} else {
/* We only deal with RPC pipes */
+ osi_Log2(smb_logp, "smb_nmpipeTransact Not a RPC vcp 0x%p fid %d",
+ vcp, fd);
code = CM_ERROR_BADFD;
}
cm_req_t req;
cm_user_t * userp;
osi_hyper_t thyper;
+ cm_scache_t *rootScp;
tp = p->parmsp + 1; /* skip over function number (always 0) */
thyper.HighPart = 0;
thyper.LowPart = 0;
- cm_HoldSCache(cm_data.rootSCachep);
- cm_ApplyDir(cm_data.rootSCachep, smb_rapCollectSharesProc, &rootShares, &thyper, userp, &req, NULL);
- cm_ReleaseSCache(cm_data.rootSCachep);
+ rootScp = cm_RootSCachep(userp, &req);
+ cm_HoldSCache(rootScp);
+ cm_ApplyDir(rootScp, smb_rapCollectSharesProc, &rootShares, &thyper, userp, &req, NULL);
+ cm_ReleaseSCache(rootScp);
cm_ReleaseUser(userp);
osi_Log1(smb_logp,"ReceiveRAPNetShareGetInfo unable to resolve user [%d]", p->uid);
return CM_ERROR_BADSMB;
}
- code = cm_NameI(cm_data.rootSCachep, shareName,
+ code = cm_NameI(cm_RootSCachep(userp, &req), shareName,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
userp, NULL, &req, &scp);
if (code == 0) {
cm_scache_t *dscp; /* dir we're dealing with */
cm_scache_t *scp; /* file we're creating */
cm_attr_t setAttr;
- int initialModeBits;
smb_fid_t *fidp;
int attributes;
clientchar_t *lastNamep;
attributes = p->parmsp[3];
dosTime = p->parmsp[4] | (p->parmsp[5] << 16);
- /* compute initial mode bits based on read-only flag in attributes */
- initialModeBits = 0666;
- if (attributes & SMB_ATTR_READONLY)
- initialModeBits &= ~0222;
-
pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[14]), NULL,
SMB_STRF_ANSIPATH);
}
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
if (lastNamep &&
#ifndef DFS_SUPPORT
if (is_ipc) {
- osi_Log0(smb_logp, "Tran2Open rejecting IPC TID");
+ osi_Log1(smb_logp, "Tran2Open rejecting IPC TID vcp %p", vcp);
smb_FreeTran2Packet(outp);
return CM_ERROR_BADFD;
}
}
dscp = NULL;
- code = cm_NameI(cm_data.rootSCachep, pathp,
+ code = cm_NameI(cm_RootSCachep(userp, &req), pathp,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
if (code != 0) {
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
- CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
- userp, tidPathp, &req, &dscp);
+ if (code == CM_ERROR_NOSUCHFILE ||
+ code == CM_ERROR_NOSUCHPATH ||
+ code == CM_ERROR_BPLUS_NOMATCH)
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+ userp, tidPathp, &req, &dscp);
cm_FreeSpace(spacep);
if (code) {
return code;
}
} else {
+ /* macintosh is expensive to program for it */
+ cm_FreeSpace(spacep);
+
#ifdef DFS_SUPPORT
if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, lastNamep);
return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
-
- /* macintosh is expensive to program for it */
- cm_FreeSpace(spacep);
}
/* if we get here, if code is 0, the file exists and is represented by
openAction = 2; /* created file */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
cm_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
+ smb_SetInitialModeBitsForFile(attributes, &setAttr);
+
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0) {
osi_hyper_t thyper;
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+ code = cm_NameI(cm_RootSCachep(userp, reqp), spacep->wdata,
caseFold, userp, tidPathp,
reqp, &dscp);
cm_FreeSpace(spacep);
responseSize = sizeof(qpi.u.QPfileAllInfo);
else if (infoLevel == SMB_QUERY_FILE_ALT_NAME_INFO)
responseSize = sizeof(qpi.u.QPfileAltNameInfo);
+ else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO)
+ responseSize = sizeof(qpi.u.QPfileStreamInfo);
else {
- osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+ osi_Log2(smb_logp, "Bad Tran2QPathInfo op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
return 0;
}
+ memset(&qpi, 0, sizeof(qpi));
pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[3]), NULL, SMB_STRF_ANSIPATH);
- osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path %S", infoLevel,
+ osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path \"%S\"", infoLevel,
osi_LogSaveClientString(smb_logp, pathp));
outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, responseSize);
outp->totalParms = 2;
else
outp->totalParms = 0;
- outp->totalData = responseSize;
/* now, if we're at infoLevel 6, we're only being asked to check
* the syntax, so we just OK things now. In particular, we're *not*
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if(code) {
+ osi_Log1(smb_logp, "ReceiveTran2QPathInfo tid path lookup failure 0x%x", code);
cm_ReleaseUser(userp);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHPATH);
smb_FreeTran2Packet(outp);
return 0;
}
+ osi_Log1(smb_logp, "T2 QPathInfo tidPathp \"%S\"",
+ osi_LogSaveClientString(smb_logp, tidPathp));
+
/*
* XXX Strange hack XXX
*
*/
if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastComp, pathp);
#ifndef SPECIAL_FOLDERS
/* Make sure that lastComp is not NULL */
if (lastComp) {
if (cm_ClientStrCmpIA(lastComp, _C("\\desktop.ini")) == 0) {
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
CM_FLAG_CASEFOLD
| CM_FLAG_DIRSEARCH
| CM_FLAG_FOLLOW,
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 == 0 ||
+ code == CM_ERROR_NOSUCHFILE ||
+ code == CM_ERROR_NOSUCHPATH ||
+ code == CM_ERROR_BPLUS_NOMATCH) {
+ /* now do namei and stat, and copy out the info */
+ code = cm_NameI(cm_RootSCachep(userp, &req), pathp,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
+ }
if (code) {
cm_ReleaseUser(userp);
smb_UnparseString(opx, qpi.u.QPfileAltNameInfo.fileName, shortName, &len, SMB_STRF_IGNORENUL);
qpi.u.QPfileAltNameInfo.fileNameLength = len;
-
- goto done;
+ responseSize = sizeof(unsigned long) + len;
}
else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
smb_UnparseString(opx, qpi.u.QPfileNameInfo.fileName, lastComp, &len, SMB_STRF_IGNORENUL);
qpi.u.QPfileNameInfo.fileNameLength = len;
-
- goto done;
+ responseSize = sizeof(unsigned long) + len;
}
else if (infoLevel == SMB_INFO_STANDARD || infoLevel == SMB_INFO_QUERY_EA_SIZE) {
cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
qpi.u.QPfileEaInfo.eaSize = 0;
}
else if (infoLevel == SMB_QUERY_FILE_ALL_INFO) {
+ smb_fid_t * fidp;
+
+ lock_ReleaseRead(&scp->rw);
+ scp_rw_held = 0;
+ fidp = smb_FindFIDByScache(vcp, scp);
+
cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
qpi.u.QPfileAllInfo.creationTime = ft;
qpi.u.QPfileAllInfo.lastAccessTime = ft;
((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
- qpi.u.QPfileAllInfo.indexNumber.HighPart = scp->fid.cell;
- qpi.u.QPfileAllInfo.indexNumber.LowPart = scp->fid.volume;
+ qpi.u.QPfileAllInfo.indexNumber.HighPart = scp->fid.vnode;
+ qpi.u.QPfileAllInfo.indexNumber.LowPart = scp->fid.unique;
qpi.u.QPfileAllInfo.eaSize = 0;
- qpi.u.QPfileAllInfo.accessFlags = 0;
- qpi.u.QPfileAllInfo.indexNumber2.HighPart = scp->fid.vnode;
- qpi.u.QPfileAllInfo.indexNumber2.LowPart = scp->fid.unique;
+ qpi.u.QPfileAllInfo.accessFlags = 0;
+ if (fidp) {
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->flags & SMB_FID_OPENDELETE)
+ qpi.u.QPfileAllInfo.accessFlags |= DELETE;
+ if (fidp->flags & SMB_FID_OPENREAD_LISTDIR)
+ qpi.u.QPfileAllInfo.accessFlags |= AFS_ACCESS_READ|AFS_ACCESS_EXECUTE;
+ if (fidp->flags & SMB_FID_OPENWRITE)
+ qpi.u.QPfileAllInfo.accessFlags |= AFS_ACCESS_WRITE;
+ if (fidp->flags & SMB_FID_DELONCLOSE)
+ qpi.u.QPfileAllInfo.deletePending = 1;
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
+ }
+ qpi.u.QPfileAllInfo.indexNumber2.HighPart = scp->fid.cell;
+ qpi.u.QPfileAllInfo.indexNumber2.LowPart = scp->fid.volume;
qpi.u.QPfileAllInfo.currentByteOffset.HighPart = 0;
qpi.u.QPfileAllInfo.currentByteOffset.LowPart = 0;
qpi.u.QPfileAllInfo.mode = 0;
smb_UnparseString(opx, qpi.u.QPfileAllInfo.fileName, lastComp, &len, SMB_STRF_IGNORENUL);
qpi.u.QPfileAllInfo.fileNameLength = len;
+ responseSize -= (sizeof(qpi.u.QPfileAllInfo.fileName) - len);
+ }
+ else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO) {
+ size_t len = 0;
+ /* For now we have no streams */
+ qpi.u.QPfileStreamInfo.nextEntryOffset = 0;
+ if (scp->fileType == CM_SCACHETYPE_FILE) {
+ qpi.u.QPfileStreamInfo.streamSize = scp->length;
+ qpi.u.QPfileStreamInfo.streamAllocationSize = scp->length;
+ smb_UnparseString(opx, qpi.u.QPfileStreamInfo.fileName, L"::$DATA", &len, SMB_STRF_IGNORENUL);
+ qpi.u.QPfileStreamInfo.streamNameLength = len;
+ responseSize -= (sizeof(qpi.u.QPfileStreamInfo.fileName) - len);
+ } else {
+ qpi.u.QPfileStreamInfo.streamSize.QuadPart = 0;
+ qpi.u.QPfileStreamInfo.streamAllocationSize.QuadPart = 0;
+ smb_UnparseString(opx, qpi.u.QPfileStreamInfo.fileName, L"", &len, SMB_STRF_IGNORENUL);
+ qpi.u.QPfileStreamInfo.streamNameLength = 0;
+ responseSize = 0;
+ }
}
+ outp->totalData = responseSize;
/* send and free the packets */
done:
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",
+ osi_Log2(smb_logp, "Bad Tran2SetPathInfo op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
smb_SendTran2Error(vcp, p, opx,
infoLevel == SMB_INFO_QUERY_ALL_EAS ? CM_ERROR_EAS_NOT_SUPPORTED : CM_ERROR_BAD_LEVEL);
*/
if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastComp, pathp);
#ifndef SPECIAL_FOLDERS
/* Make sure that lastComp is not NULL */
if (lastComp) {
if (cm_ClientStrCmpI(lastComp, _C("\\desktop.ini")) == 0) {
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
CM_FLAG_CASEFOLD
| CM_FLAG_DIRSEARCH
| CM_FLAG_FOLLOW,
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 == 0 ||
+ code == CM_ERROR_NOSUCHFILE ||
+ code == CM_ERROR_NOSUCHPATH ||
+ code == CM_ERROR_BPLUS_NOMATCH) {
+ /* now do namei and stat, and copy out the info */
+ code = cm_NameI(cm_RootSCachep(userp, &req), pathp,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
+ }
+
if (code) {
cm_ReleaseUser(userp);
smb_SendTran2Error(vcp, p, opx, code);
}
if (spi->u.QPstandardInfo.attributes != 0) {
- if ((scp->unixModeBits & 0222)
+ if ((scp->unixModeBits & 0200)
&& (spi->u.QPstandardInfo.attributes & SMB_ATTR_READONLY) != 0) {
/* make a writable file read-only */
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
attr.unixModeBits = scp->unixModeBits & ~0222;
}
- else if ((scp->unixModeBits & 0222) == 0
+ else if ((scp->unixModeBits & 0200) == 0
&& (spi->u.QPstandardInfo.attributes & SMB_ATTR_READONLY) == 0) {
/* make a read-only file writable */
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
fidp = smb_FindFID(vcp, fid, 0);
if (fidp == NULL) {
+ osi_Log2(smb_logp, "Tran2QFileInfo Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
return 0;
}
responseSize = sizeof(qfi.u.QFeaInfo);
else if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
responseSize = sizeof(qfi.u.QFfileNameInfo);
+ else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO)
+ responseSize = sizeof(qfi.u.QFfileStreamInfo);
else {
- osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+ osi_Log2(smb_logp, "Bad Tran2QFileInfo op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
smb_ReleaseFID(fidp);
return 0;
}
osi_Log2(smb_logp, "T2 QFileInfo type 0x%x fid %d", infoLevel, fid);
+ memset(&qfi, 0, sizeof(qfi));
outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, responseSize);
outp->totalParms = 2;
else
outp->totalParms = 0;
- outp->totalData = responseSize;
userp = smb_GetTran2User(vcp, p);
if (!userp) {
lock_ReleaseMutex(&fidp->mx);
smb_UnparseString(opx, qfi.u.QFfileNameInfo.fileName, name, &len, SMB_STRF_IGNORENUL);
- outp->totalData = len + 4; /* this is actually what we want to return */
+ responseSize = len + 4; /* this is actually what we want to return */
qfi.u.QFfileNameInfo.fileNameLength = len;
}
+ else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO) {
+ size_t len = 0;
+
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_INVALID) {
+ /* Do not return the alternate streams for directories */
+ responseSize = 0;
+ } else {
+ /* For now we have no alternate streams */
+ qfi.u.QFfileStreamInfo.nextEntryOffset = 0;
+ qfi.u.QFfileStreamInfo.streamSize = scp->length;
+ qfi.u.QFfileStreamInfo.streamAllocationSize = scp->length;
+ smb_UnparseString(opx, qfi.u.QFfileStreamInfo.fileName, L"::$DATA", &len, SMB_STRF_IGNORENUL);
+ qfi.u.QFfileStreamInfo.streamNameLength = len;
+ responseSize -= (sizeof(qfi.u.QFfileStreamInfo.fileName) - len);
+ }
+ }
+ outp->totalData = responseSize;
/* send and free the packets */
done:
fidp = smb_FindFID(vcp, fid, 0);
if (fidp == NULL) {
+ osi_Log2(smb_logp, "Tran2SetFileInfo Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
return 0;
}
infoLevel = p->parmsp[1];
osi_Log2(smb_logp,"ReceiveTran2SetFileInfo type 0x%x fid %d", infoLevel, fid);
if (infoLevel > SMB_SET_FILE_END_OF_FILE_INFO || infoLevel < SMB_SET_FILE_BASIC_INFO) {
- osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+ osi_Log2(smb_logp, "Bad Tran2SetFileInfo op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
smb_ReleaseFID(fidp);
attribute = sfi->u.QFbasicInfo.attributes;
if (attribute != 0) {
- if ((scp->unixModeBits & 0222)
+ if ((scp->unixModeBits & 0200)
&& (attribute & SMB_ATTR_READONLY) != 0) {
/* make a writable file read-only */
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
attr.unixModeBits = scp->unixModeBits & ~0222;
}
- else if ((scp->unixModeBits & 0222) == 0
+ else if ((scp->unixModeBits & 0200) == 0
&& (attribute & SMB_ATTR_READONLY) == 0) {
/* make a read-only file writable */
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
* for might be a known name with the final character stripped
* off.
*/
- code = cm_NameI(cm_data.rootSCachep, &requestFileName[nbnLen+2],
+ code = cm_NameI(cm_RootSCachep(userp, &req), &requestFileName[nbnLen+2],
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
userp, NULL, &req, &scp);
if (code == 0 ||
cm_ReleaseSCache(scp);
scp = 0;
}
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(pathName, &lastComponent, temp);
- code = cm_NameI(cm_data.rootSCachep, pathName,
+ code = cm_NameI(cm_RootSCachep(userp, &req), pathName,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, NULL, &req, &dscp);
if (code == 0) {
*q = '\0';
if (smb_FindShare(vcp, vcp->usersp, shareName, &p)) {
- code = cm_NameI(cm_data.rootSCachep, _C(""),
+ code = cm_NameI(cm_RootSCachep(userp, &req), _C(""),
CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
userp, p, &req, &scp);
free(p);
/* try to get the vnode for the path name next */
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, NULL, pathp);
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if (code) {
return 0;
}
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
cm_FreeSpace(spacep);
code = 0;
} else {
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, NULL, pathp);
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if (code) {
cm_ClientStrCpy(dsp->tidPath, lengthof(dsp->tidPath), tidPathp ? tidPathp : _C("/"));
cm_ClientStrCpy(dsp->relPath, lengthof(dsp->relPath), spacep->wdata);
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
cm_FreeSpace(spacep);
cm_scache_t *dscp; /* dir we're dealing with */
cm_scache_t *scp; /* file we're creating */
cm_attr_t setAttr;
- int initialModeBits;
smb_fid_t *fidp;
int attributes;
clientchar_t *lastNamep;
attributes = smb_GetSMBParm(inp, 5);
dosTime = smb_GetSMBParm(inp, 6) | (smb_GetSMBParm(inp, 7) << 16);
- /* compute initial mode bits based on read-only flag in attributes */
- initialModeBits = 0666;
- if (attributes & SMB_ATTR_READONLY)
- initialModeBits &= ~0222;
-
pathp = smb_ParseASCIIBlock(inp, smb_GetSMBData(inp, NULL), NULL,
SMB_STRF_ANSIPATH);
if (!pathp)
}
spacep = inp->spacep;
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
if (lastNamep &&
userp = smb_GetUserFromVCP(vcp, inp);
dscp = NULL;
- code = cm_NameI(cm_data.rootSCachep, pathp,
+ code = cm_NameI(cm_RootSCachep(userp, &req), pathp,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
#endif /* DFS_SUPPORT */
if (code != 0) {
- code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
- CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
- userp, tidPathp, &req, &dscp);
+ if (code == CM_ERROR_NOSUCHFILE ||
+ code == CM_ERROR_NOSUCHPATH ||
+ code == CM_ERROR_BPLUS_NOMATCH)
+ code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+ userp, tidPathp, &req, &dscp);
if (code) {
cm_ReleaseUser(userp);
return code;
openAction = 2; /* created file */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
+ smb_SetInitialModeBitsForFile(attributes, &setAttr);
+
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0) {
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "V3LockingX Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
return CM_ERROR_BADFD;
-
+ }
lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
lock_ReleaseMutex(&fidp->mx);
userp, &req, &lockp);
}
- if (code == CM_ERROR_WOULDBLOCK && Timeout != 0) {
+ if (code == CM_ERROR_LOCK_NOT_GRANTED && Timeout != 0) {
smb_waitingLock_t * wLock;
/* Put on waiting list */
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "V3GetAttributes Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
return CM_ERROR_BADFD;
-
+ }
lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
lock_ReleaseMutex(&fidp->mx);
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "V3SetAttributes Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
return CM_ERROR_BADFD;
-
+ }
lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
lock_ReleaseMutex(&fidp->mx);
if (*inp->wctp == 14) {
/* we have a request with 64-bit file offsets */
-#ifdef AFS_LARGEFILES
offset.HighPart = smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16);
-#else
- if ((smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16)) != 0) {
- /* uh oh */
- osi_Log0(smb_logp, "smb_ReceiveV3WriteX offset requires largefile support");
- /* we shouldn't have received this op if we didn't specify
- largefile support */
- return CM_ERROR_BADOP;
- }
-#endif
}
op = inp->data + smb_GetSMBParm(inp, 11);
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveV3WriteX Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
return CM_ERROR_BADFD;
-
+ }
lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
lock_ReleaseMutex(&fidp->mx);
*/
lock_ObtainMutex(&fidp->mx);
if ((fidp->flags & SMB_FID_MTIMESETDONE) != SMB_FID_MTIMESETDONE) {
+ lock_ObtainWrite(&fidp->scp->rw);
scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
scp->clientModTime = time(NULL);
+ lock_ReleaseWrite(&fidp->scp->rw);
}
lock_ReleaseMutex(&fidp->mx);
if (*inp->wctp == 12) {
/* a request with 64-bit offsets */
-#ifdef AFS_LARGEFILES
offset.HighPart = smb_GetSMBParm(inp, 10) | (smb_GetSMBParm(inp, 11) << 16);
if (LargeIntegerLessThanZero(offset)) {
offset.HighPart, offset.LowPart);
return CM_ERROR_BADSMB;
}
-#else
- if ((smb_GetSMBParm(inp, 10) | (smb_GetSMBParm(inp, 11) << 16)) != 0) {
- osi_Log0(smb_logp, "smb_ReceiveV3Read offset is 64-bit. Dropping");
- return CM_ERROR_BADSMB;
- } else {
- offset.HighPart = 0;
- }
-#endif
} else {
offset.HighPart = 0;
}
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveV3Read Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
return CM_ERROR_BADFD;
}
unsigned int createDisp;
unsigned int createOptions;
unsigned int shareAccess;
- int initialModeBits;
unsigned short baseFid;
smb_fid_t *baseFidp;
smb_fid_t *fidp;
else
realDirFlag = -1;
- /*
- * compute initial mode bits based on read-only flag in
- * extended attributes
- */
- initialModeBits = 0666;
- if (extAttributes & SMB_ATTR_READONLY)
- initialModeBits &= ~0222;
-
pathp = smb_ParseStringCb(inp, smb_GetSMBData(inp, NULL), nameLength,
NULL, SMB_STRF_ANSIPATH);
realPathp[nameLength/sizeof(clientchar_t)] = 0;
spacep = inp->spacep;
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, realPathp);
osi_Log1(smb_logp,"NTCreateX for [%S]",osi_LogSaveClientString(smb_logp,realPathp));
if (baseFid == 0) {
baseFidp = NULL;
- baseDirp = cm_data.rootSCachep;
+ baseDirp = cm_RootSCachep(cm_rootUserp, &req);
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if (code == CM_ERROR_TIDIPC) {
/* Attempt to use a TID allocated for IPC. The client
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
- if (baseFidp)
+ if (baseFidp)
smb_ReleaseFID(baseFidp);
return CM_ERROR_EXISTS;
}
}
+ /* we have both scp and dscp */
}
- /* we have both scp and dscp */
} else {
code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
/* we might have scp but not dscp */
}
+ if (code &&
+ code != CM_ERROR_NOSUCHFILE &&
+ code != CM_ERROR_NOSUCHPATH &&
+ code != CM_ERROR_BPLUS_NOMATCH) {
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if (baseFidp)
+ smb_ReleaseFID(baseFidp);
+ return code;
+ }
+
if (scp)
foundscp = TRUE;
#endif /* DFS_SUPPORT */
if (code &&
+ (code == CM_ERROR_NOSUCHFILE ||
+ code == CM_ERROR_NOSUCHPATH ||
+ code == CM_ERROR_BPLUS_NOMATCH) &&
(tp = cm_ClientStrRChr(spacep->wdata, '\\')) &&
(createDisp == FILE_CREATE) &&
(realDirFlag == 1)) {
openAction = 2; /* created file */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
+ smb_SetInitialModeBitsForFile(extAttributes, &setAttr);
+
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, &req);
if (code == 0) {
created = 1;
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
+ smb_SetInitialModeBitsForDir(extAttributes, &setAttr);
pp = treeStartp;
cp = spacep->wdata;
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
free(realPathp);
- return code;
+ return CM_ERROR_SHARING_VIOLATION;
}
}
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fidp->fid;
- /* out parms */
- parmSlot = 2;
lock_ObtainRead(&scp->rw);
- smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */
- smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
- smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
- cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
- smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp));
- parmSlot += 2;
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* dev state */
- smb_SetSMBParmByte(outp, parmSlot,
- (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
- scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
- scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
- smb_SetSMBDataLength(outp, 0);
+
+ /*
+ * Always send the standard response. Sending the extended
+ * response results in the Explorer Shell being unable to
+ * access directories at random times.
+ */
+ if (1 /*!extendedRespRequired */) {
+ /* out parms */
+ parmSlot = 2;
+ smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */
+ smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
+ smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp));
+ parmSlot += 2;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+ smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
+ smb_SetSMBParm(outp, parmSlot, NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS);
+ parmSlot++; /* dev state */
+ smb_SetSMBParmByte(outp, parmSlot,
+ (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
+ smb_SetSMBDataLength(outp, 0);
+ } else {
+ /* out parms */
+ parmSlot = 2;
+ smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */
+ smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
+ smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp));
+ parmSlot += 2;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+ smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
+ smb_SetSMBParm(outp, parmSlot, NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS);
+ parmSlot++; /* dev state */
+ smb_SetSMBParmByte(outp, parmSlot,
+ (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
+ /* Setting the GUID results in a failure with cygwin */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ /* Maxmimal access rights */
+ smb_SetSMBParmLong(outp, parmSlot, 0x001f01ff); parmSlot += 2;
+ /* Guest access rights */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBDataLength(outp, 0);
+ }
if ((fidp->flags & SMB_FID_EXECUTABLE) &&
LargeIntegerGreaterThanZero(scp->length) &&
unsigned int impLevel;
unsigned int secFlags;
unsigned int createOptions;
- int initialModeBits;
unsigned short baseFid;
smb_fid_t *baseFidp;
smb_fid_t *fidp;
else
realDirFlag = -1;
- /*
- * compute initial mode bits based on read-only flag in
- * extended attributes
- */
- initialModeBits = 0666;
- if (extAttributes & SMB_ATTR_READONLY)
- initialModeBits &= ~0222;
-
pathp = smb_ParseStringCb(inp, (parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR)),
nameLength, NULL, SMB_STRF_ANSIPATH);
/* Sometimes path is not nul-terminated, so we make a copy. */
memcpy(realPathp, pathp, nameLength);
realPathp[nameLength/sizeof(clientchar_t)] = 0;
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, realPathp);
osi_Log1(smb_logp,"NTTranCreate %S",osi_LogSaveStringW(smb_logp,realPathp));
if (baseFid == 0) {
baseFidp = NULL;
- baseDirp = cm_data.rootSCachep;
+ baseDirp = cm_RootSCachep(cm_rootUserp, &req);
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if (code == CM_ERROR_TIDIPC) {
/* Attempt to use a TID allocated for IPC. The client
} else {
baseFidp = smb_FindFID(vcp, baseFid, 0);
if (!baseFidp) {
- osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
+ osi_Log2(smb_logp, "NTTranCreate Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, baseFid);
free(realPathp);
cm_ReleaseUser(userp);
return CM_ERROR_BADFD;
return CM_ERROR_EXISTS;
}
}
- } else
- dscp = NULL;
+ }
} else {
code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
if (code == 0)
foundscp = TRUE;
- if (code != 0 || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
+ if (code == CM_ERROR_NOSUCHFILE ||
+ code == CM_ERROR_NOSUCHPATH ||
+ code == CM_ERROR_BPLUS_NOMATCH ||
+ (code == 0 && (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)))) {
/* look up parent directory */
if ( !dscp ) {
code = cm_NameI(baseDirp, spacep->wdata,
openAction = 2; /* created file */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
+ smb_SetInitialModeBitsForFile(extAttributes, &setAttr);
+
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0) {
openAction = 2; /* created directory */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
+ smb_SetInitialModeBitsForDir(extAttributes, &setAttr);
+
code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req, NULL);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_ADDED,
*((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
*((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
*((USHORT *)outData) = 0; outData += 2; /* filetype */
- *((USHORT *)outData) = 0; outData += 2; /* dev state */
+ *((USHORT *)outData) = NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS;
+ outData += 2; /* dev state */
*((USHORT *)outData) = ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
*((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
*((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
*((USHORT *)outData) = 0; outData += 2; /* filetype */
- *((USHORT *)outData) = 0; outData += 2; /* dev state */
+ *((USHORT *)outData) = NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS;
+ outData += 2; /* dev state */
*((USHORT *)outData) = ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
outData += 1; /* is a dir? */
- memset(outData,0,24); outData += 24; /* Volume ID and file ID */
+ /* Setting the GUID results in failures with cygwin */
+ memset(outData,0,24); outData += 24; /* GUID */
*((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
*((ULONG *)outData) = 0; outData += 4; /* Guest Access rights */
}
fidp = smb_FindFID(vcp, fid, 0);
if (!fidp) {
- osi_Log1(smb_logp, "ERROR: NotifyChange given invalid fid [%d]", fid);
+ osi_Log2(smb_logp, "NotifyChange Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
return CM_ERROR_BADFD;
}
return 0;
}
-unsigned char nullSecurityDesc[36] = {
+unsigned char nullSecurityDesc[] = {
0x01, /* security descriptor revision */
0x00, /* reserved, should be zero */
- 0x00, 0x80, /* security descriptor control;
- * 0x8000 : self-relative format */
+ 0x04, 0x80, /* security descriptor control;
+ * 0x0004 : null-DACL present - everyone has full access
+ * 0x8000 : relative format */
0x14, 0x00, 0x00, 0x00, /* offset of owner SID */
- 0x1c, 0x00, 0x00, 0x00, /* offset of group SID */
+ 0x20, 0x00, 0x00, 0x00, /* offset of group SID */
0x00, 0x00, 0x00, 0x00, /* offset of DACL would go here */
0x00, 0x00, 0x00, 0x00, /* offset of SACL would go here */
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* "null SID" owner SID */
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- /* "null SID" group SID */
+ 0x01, 0x01, 0x00, 0x00, /* "everyone SID" owner SID */
+ 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x00, 0x00, /* "everyone SID" owner SID */
+ 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00
};
/* NT_TRANSACT_QUERY_SECURITY_DESC (SMB_COM_NT_TRANSACT) */
long smb_ReceiveNTTranQuerySecurityDesc(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
int parmOffset, parmCount, dataOffset, dataCount;
+ int totalParmCount, totalDataCount;
int parmSlot;
- int maxData;
+ int maxData, maxParm;
+ int inTotalParm, inTotalData;
+ int inParm, inData;
+ int inParmOffset, inDataOffset;
char *outData;
char *parmp;
USHORT *sparmp;
ULONG *lparmp;
USHORT fid;
ULONG securityInformation;
+ smb_fid_t *fidp;
+ long code = 0;
+ DWORD dwLength;
- parmOffset = smb_GetSMBOffsetParm(inp, 11, 1)
+ /*
+ * For details on the meanings of the various
+ * SMB_COM_TRANSACTION fields, see sections 2.2.4.33
+ * of http://msdn.microsoft.com/en-us/library/ee442092%28PROT.13%29.aspx
+ */
+
+ inTotalParm = smb_GetSMBOffsetParm(inp, 1, 1)
+ | (smb_GetSMBOffsetParm(inp, 2, 1) << 16);
+
+ inTotalData = smb_GetSMBOffsetParm(inp, 3, 1)
+ | (smb_GetSMBOffsetParm(inp, 4, 1) << 16);
+
+ maxParm = smb_GetSMBOffsetParm(inp, 5, 1)
+ | (smb_GetSMBOffsetParm(inp, 6, 1) << 16);
+
+ maxData = smb_GetSMBOffsetParm(inp, 7, 1)
+ | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
+
+ inParm = smb_GetSMBOffsetParm(inp, 9, 1)
+ | (smb_GetSMBOffsetParm(inp, 10, 1) << 16);
+
+ inParmOffset = smb_GetSMBOffsetParm(inp, 11, 1)
| (smb_GetSMBOffsetParm(inp, 12, 1) << 16);
- parmp = inp->data + parmOffset;
+
+ inData = smb_GetSMBOffsetParm(inp, 13, 1)
+ | (smb_GetSMBOffsetParm(inp, 14, 1) << 16);
+
+ inDataOffset = smb_GetSMBOffsetParm(inp, 15, 1)
+ | (smb_GetSMBOffsetParm(inp, 16, 1) << 16);
+
+ parmp = inp->data + inParmOffset;
sparmp = (USHORT *) parmp;
lparmp = (ULONG *) parmp;
fid = sparmp[0];
securityInformation = lparmp[1];
- maxData = smb_GetSMBOffsetParm(inp, 7, 1)
- | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
+ fidp = smb_FindFID(vcp, fid, 0);
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveNTTranQuerySecurityDesc Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
+ return CM_ERROR_BADFD;
+ }
- if (maxData < 36)
- dataCount = 0;
- else
- dataCount = 36;
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_CloseFID(vcp, fidp, NULL, 0);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_NOSUCHFILE;
+ }
+ lock_ReleaseMutex(&fidp->mx);
+
+ osi_Log4(smb_logp,"smb_ReceiveNTTranQuerySecurityDesc fidp 0x%p scp 0x%p file \"%S\" Info=0x%x",
+ fidp, fidp->scp, osi_LogSaveClientString(smb_logp, fidp->NTopen_wholepathp),
+ securityInformation);
+
+ smb_ReleaseFID(fidp);
+
+ if ( securityInformation & ~(OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION) )
+ {
+ code = CM_ERROR_BAD_LEVEL;
+ goto done;
+ }
+
+ dwLength = sizeof( nullSecurityDesc);
+
+ totalDataCount = dwLength;
+ totalParmCount = 4;
+
+ if (maxData >= totalDataCount) {
+ dataCount = totalDataCount;
+ parmCount = min(totalParmCount, maxParm);
+ } else if (maxParm >= totalParmCount) {
+ totalDataCount = dataCount = 0;
+ parmCount = totalParmCount;
+ } else {
+ totalDataCount = dataCount = 0;
+ totalParmCount = parmCount = 0;
+ }
/* out parms */
parmOffset = 8*4 + 39;
parmOffset += 1; /* pad to 4 */
- parmCount = 4;
+
dataOffset = parmOffset + parmCount;
parmSlot = 1;
outp->oddByte = 1;
/* Total Parameter Count */
- smb_SetSMBParmLong(outp, parmSlot, parmCount); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, totalParmCount); parmSlot += 2;
/* Total Data Count */
- smb_SetSMBParmLong(outp, parmSlot, dataCount); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, totalDataCount); parmSlot += 2;
/* Parameter Count */
smb_SetSMBParmLong(outp, parmSlot, parmCount); parmSlot += 2;
/* Parameter Offset */
- smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, parmCount ? parmOffset : 0); parmSlot += 2;
/* Parameter Displacement */
smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
/* Data Count */
smb_SetSMBParmLong(outp, parmSlot, dataCount); parmSlot += 2;
/* Data Offset */
- smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, dataCount ? dataOffset : 0); parmSlot += 2;
/* Data Displacement */
smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
- smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
- smb_SetSMBDataLength(outp, 1 + parmCount + dataCount);
+ /* Setup Count */
+ smb_SetSMBParmByte(outp, parmSlot, 0);
- outData = smb_GetSMBData(outp, NULL);
- outData++; /* round to get to parmOffset */
- *((ULONG *)outData) = 36; outData += 4; /* length */
+ if (parmCount == totalParmCount && dwLength == dataCount) {
+ smb_SetSMBDataLength(outp, 1 + parmCount + dataCount);
- if (maxData >= 36) {
- memcpy(outData, nullSecurityDesc, 36);
- outData += 36;
- return 0;
- } else
- return CM_ERROR_BUFFERTOOSMALL;
+ /* Data */
+ outData = smb_GetSMBData(outp, NULL);
+ outData++; /* round to get to dataOffset */
+
+ *((ULONG *)outData) = dataCount; outData += 4; /* SD Length (4 bytes) */
+ memcpy(outData, nullSecurityDesc, dataCount);
+ outData += dataCount;
+
+ code = 0;
+ } else if (parmCount >= 4) {
+ smb_SetSMBDataLength(outp, 1 + parmCount);
+
+ /* Data */
+ outData = smb_GetSMBData(outp, NULL);
+ outData++; /* round to get to dataOffset */
+
+ *((ULONG *)outData) = dwLength; outData += 4; /* SD Length (4 bytes) */
+ code = CM_ERROR_BUFFERTOOSMALL;
+ } else {
+ smb_SetSMBDataLength(outp, 0);
+ code = CM_ERROR_BUFFER_OVERFLOW;
+ }
+
+ done:
+ return code;
}
/* SMB_COM_NT_TRANSACT
osi_Log0(smb_logp, "SMB NT Transact Set Quota - not implemented");
break;
}
- return CM_ERROR_INVAL;
+ return CM_ERROR_BADOP;
}
/*
return userp;
}
+cm_user_t *smb_FindCMUserBySID(clientchar_t *usern, clientchar_t *machine, afs_uint32 flags)
+{
+ smb_username_t *unp;
+ cm_user_t * userp;
+
+ unp = smb_FindUserByName(usern, machine, flags);
+ if (!unp->userp) {
+ lock_ObtainMutex(&unp->mx);
+ unp->flags |= SMB_USERNAMEFLAG_SID;
+ unp->userp = cm_NewUser();
+ lock_ReleaseMutex(&unp->mx);
+ osi_Log2(smb_logp,"smb_FindCMUserBySID New user name[%S] machine[%S]",osi_LogSaveClientString(smb_logp,usern),osi_LogSaveClientString(smb_logp,machine));
+ } else {
+ osi_Log2(smb_logp,"smb_FindCMUserBySID Found name[%S] machine[%S]",osi_LogSaveClientString(smb_logp,usern),osi_LogSaveClientString(smb_logp,machine));
+ }
+ userp = unp->userp;
+ cm_HoldUser(userp);
+ smb_ReleaseUsername(unp);
+ return userp;
+}