+
/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
*/
+#include <afsconfig.h>
#include <afs/param.h>
+#include <roken.h>
+
#include <afs/stds.h>
#include <windows.h>
#include <ntstatus.h>
#define SECURITY_WIN32
#include <security.h>
+#include <sddl.h>
#include <lmaccess.h>
#pragma warning(pop)
#include <stdlib.h>
#include <WINNT\afsreg.h>
#include "smb.h"
+#include "msrpc.h"
#include <strsafe.h>
extern osi_hyper_t hzero;
{
smb_user_t *uidp;
cm_user_t *up = NULL;
-
+
uidp = smb_FindUID(vcp, inp->uid, 0);
- if (!uidp)
+ if (!uidp)
return NULL;
-
+
up = smb_GetUserFromUID(uidp);
smb_ReleaseUID(uidp);
return up;
}
-/*
- * Return boolean specifying if the path name is thought to be an
+/*
+ * Return boolean specifying if the path name is thought to be an
* executable file. For now .exe or .dll.
*/
afs_uint32 smb_IsExecutableFileName(const clientchar_t *name)
{
int i, j, len;
-
+
if ( smb_ExecutableExtensions == NULL || name == NULL)
return 0;
attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
} else if (scp->fid.vnode & 0x1)
attrs = SMB_ATTR_DIRECTORY;
- else
+ else
attrs = 0;
/*
* 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
clientchar_t tc;
while (tc = *maskp++)
- if (tc == '?' || tc == '*' || tc == '<' || tc == '>')
+ if (tc == '?' || tc == '*' || tc == '<' || tc == '>')
return 1;
return 0;
}
va_start( args, format );
cm_ClientStrPrintfV(vbuffer, lengthof(vbuffer), format, args);
osi_Log1(smb_logp, "%S", osi_LogSaveClientString(smb_logp, vbuffer));
- cm_ClientStrCat(vbuffer, lengthof(vbuffer), _C("\n"));
- OutputDebugStringW(vbuffer);
}
void OutputDebugHexDump(unsigned char * buffer, int len) {
if(!(i%16)) {
if(i) {
osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
- StringCchCatA(buf, lengthof(buf), "\r\n");
- OutputDebugString(buf);
}
StringCchPrintfA(buf, lengthof(buf), "%5x", i);
memset(buf+5,' ',80);
j = j + 56 + ((j>7)?1:0);
buf[j] = (k>32 && k<127)?k:'.';
- }
+ }
if(i) {
osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
- StringCchCatA(buf, lengthof(buf), "\r\n");
- OutputDebugString(buf);
- }
+ }
}
#define SMB_EXT_SEC_PACKAGE_NAME "Negotiate"
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;
int partialTokenLen;
void * partialToken;
-};
+};
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;
OutputDebugF(_C("Received incoming token:"));
OutputDebugHexDump(secBlobIn,secBlobInLength);
}
-
+
if (secCtx) {
- OutputDebugF(_C("Continuing with existing context."));
+ OutputDebugF(_C("Continuing with existing context."));
creds = secCtx->creds;
ctx = secCtx->ctx;
code = CM_ERROR_GSSCONTINUE;
}
- if ((status == SEC_I_COMPLETE_NEEDED || status == SEC_E_OK ||
- status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) &&
+ if ((status == SEC_I_COMPLETE_NEEDED || status == SEC_E_OK ||
+ status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) &&
secTokOut.pvBuffer) {
OutputDebugF(_C("Need to send token back to client"));
if (status == SEC_E_OK || status == SEC_I_COMPLETE_NEEDED) {
/* woo hoo! */
+ HANDLE hToken = 0;
SecPkgContext_NamesW names;
OutputDebugF(_C("Authentication completed"));
} else {
/* Force the user to retry if the context is invalid */
OutputDebugF(_C("QueryContextAttributes Names failed [%x]"), GetLastError());
- code = CM_ERROR_BADPASSWORD;
+ 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 ) {
#define P_LEN 256
#define P_RESP_LEN 128
-/* LsaLogonUser expects input parameters to be in a contiguous block of memory.
+/* LsaLogonUser expects input parameters to be in a contiguous block of memory.
So put stuff in a struct. */
struct Lm20AuthBlob {
MSV1_0_LM20_LOGON lmlogon;
TOKEN_SOURCE tsource;
};
-long smb_AuthenticateUserLM(smb_vc_t *vcp, clientchar_t * accountName, clientchar_t * primaryDomain, char * ciPwd, unsigned ciPwdLength, char * csPwd, unsigned csPwdLength)
+long smb_AuthenticateUserLM(smb_vc_t *vcp, clientchar_t * accountName, clientchar_t * primaryDomain, char * ciPwd, unsigned ciPwdLength, char * csPwd, unsigned csPwdLength)
{
NTSTATUS nts, ntsEx;
struct Lm20AuthBlob lmAuth;
memset(&lmAuth,0,sizeof(lmAuth));
lmAuth.lmlogon.MessageType = MsV1_0NetworkLogon;
-
+
lmAuth.lmlogon.LogonDomainName.Buffer = lmAuth.primaryDomainW;
cm_ClientStringToUtf16(primaryDomain, -1, lmAuth.primaryDomainW, P_LEN);
lmAuth.lmlogon.LogonDomainName.Length = (USHORT)(wcslen(lmAuth.primaryDomainW) * sizeof(WCHAR));
return CM_ERROR_BADLOGONTYPE;
else /* our catchall is a bad password though we could be more specific */
return CM_ERROR_BADPASSWORD;
- }
+ }
}
/* The buffer pointed to by usern is assumed to be at least SMB_MAX_USERNAME_LENGTH bytes */
-long smb_GetNormalizedUsername(clientchar_t * usern, const clientchar_t * accountName, const clientchar_t * domainName)
+long smb_GetNormalizedUsername(clientchar_t * usern, const clientchar_t * accountName, const clientchar_t * domainName)
{
clientchar_t * atsign;
const clientchar_t * domain;
it will either return an empty string or a '?' */
if (!domain[0] || domain[0] == '?')
/* Empty domains and empty usernames are usually sent from tokenless contexts.
- This way such logins will get an empty username (easy to check). I don't know
+ This way such logins will get an empty username (easy to check). I don't know
when a non-empty username would be supplied with an anonymous domain, but *shrug* */
cm_ClientStrCpy(usern, SMB_MAX_USERNAME_LENGTH, accountName);
else {
}
/* When using SMB auth, all SMB sessions have to pass through here
- * first to authenticate the user.
+ * first to authenticate the user.
*
* Caveat: If not using SMB auth, the protocol does not require
* sending a session setup packet, which means that we can't rely on a
unsigned long caps = 0;
smb_username_t *unp;
clientchar_t *s1 = _C(" ");
- long code = 0;
+ 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;
/* Check for bad conns */
if (vcp->flags & SMB_VCFLAG_REMOTECONN)
return CM_ERROR_REMOTECONN;
+ /* maxBufferSize */
+ maxBufferSize = smb_GetSMBParm(inp, 2);
+ maxMpxCount = smb_GetSMBParm(inp, 3);
+ vcNumber = smb_GetSMBParm(inp, 4);
+
+ osi_Log3(smb_logp, "SESSION_SETUP_ANDX with MaxBufferSize=%d, MaxMpxCount=%d, VCNumber=%d",
+ maxBufferSize, maxMpxCount, vcNumber);
+
+ if (maxMpxCount > smb_maxMpxRequests) {
+ LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_MAX_MPX_COUNT, maxMpxCount, smb_maxMpxRequests);
+ osi_Log2(smb_logp, "MaxMpxCount for client is too large (Client=%d, Server=%d)",
+ maxMpxCount, smb_maxMpxRequests);
+ }
+
+ if (maxBufferSize < SMB_PACKETSIZE) {
+ LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_MAX_BUFFER_SIZE, maxBufferSize, SMB_PACKETSIZE);
+ osi_Log2(smb_logp, "MaxBufferSize for client is too small (Client=%d, Server=%d)",
+ maxBufferSize, SMB_PACKETSIZE);
+ }
+
+ if (vcNumber == 0) {
+ osi_Log0(smb_logp, "Resetting all VCs");
+ smb_MarkAllVCsDead(vcp);
+ }
+
if (vcp->flags & SMB_VCFLAG_USENT) {
if (smb_authType == SMB_AUTH_EXTENDED) {
/* extended authentication */
int secBlobInLength;
OutputDebugF(_C("NT Session Setup: Extended"));
-
+
if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) {
caps = smb_GetSMBParm(inp,10) | (((unsigned long) smb_GetSMBParm(inp,11)) << 16);
}
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;
free(secBlobOut);
tp += secBlobOutLength;
cb_data += secBlobOutLength;
- }
+ }
tp = smb_UnparseString(outp, tp, smb_ServerOS, &cb_data, 0);
tp = smb_UnparseString(outp, tp, smb_ServerLanManager, &cb_data, 0);
tp = smb_UnparseString(outp, tp, smb_ServerDomainName, &cb_data, 0);
/* for the moment we can only deal with NTSTATUS */
if (caps & NTNEGOTIATE_CAPABILITY_NTSTATUS) {
vcp->flags |= SMB_VCFLAG_STATUS32;
- }
+ }
#ifdef SMB_UNICODE
if ((caps & NTNEGOTIATE_CAPABILITY_UNICODE) && smb_UseUnicode) {
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 = smb_FindUserByName(usern, vcp->rname, SMB_FLAG_CREATE);
lock_ObtainMutex(&unp->mx);
if (unp->flags & SMB_USERNAMEFLAG_AFSLOGON) {
- /* clear the afslogon flag so that the tickets can now
+ /* clear the afslogon flag so that the tickets can now
* be freed when the refCount returns to zero.
*/
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 */
free(secBlobOut);
tp += secBlobOutLength;
cb_data += secBlobOutLength;
- }
+ }
tp = smb_UnparseString(outp, tp, smb_ServerOS, &cb_data, 0);
tp = smb_UnparseString(outp, tp, smb_ServerLanManager, &cb_data, 0);
}
}
+ if (secSidString)
+ LocalFree(secSidString);
return 0;
}
smb_ReleaseUID(uidp);
}
- else
+ else
osi_Log0(smb_logp, "SMB3 user logoffX");
smb_SetSMBDataLength(outp, 0);
clientchar_t *servicep;
cm_user_t *userp = NULL;
int ipc = 0;
-
+
osi_Log0(smb_logp, "SMB3 receive tree connect");
/* parse input parameters */
lock_ObtainMutex(&vcp->mx);
newTid = vcp->tidCounter++;
lock_ReleaseMutex(&vcp->mx);
-
+
tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
if (!ipc) {
dwAdvertiseDFS = 0;
RegCloseKey (parmKey);
}
- smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS |
+ smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS |
(dwAdvertiseDFS ? SMB_SHARE_IS_IN_DFS : 0) |
(policy << 2));
}
lock_ObtainMutex(&tidp->mx);
tidp->userp = userp;
tidp->pathname = sharePath;
- if (ipc)
+ if (ipc)
tidp->flags |= SMB_TIDFLAG_IPC;
lock_ReleaseMutex(&tidp->mx);
smb_ReleaseTID(tidp, FALSE);
{
smb_tran2Packet_t *tp;
smb_t *smbp;
-
+
smbp = (smb_t *) inp->data;
for (tp = smb_tran2AssemblyQueuep; tp; tp = (smb_tran2Packet_t *) osi_QNext(&tp->q)) {
if (tp->vcp == vcp && tp->mid == smbp->mid && tp->tid == smbp->tid)
{
smb_tran2Packet_t *tp;
smb_t *smbp;
-
+
smbp = (smb_t *) inp->data;
tp = malloc(sizeof(*tp));
memset(tp, 0, sizeof(*tp));
smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
smb_tran2Packet_t *inp, smb_packet_t *outp,
- int totalParms, int totalData)
+ int totalParms, int totalData)
{
smb_tran2Packet_t *tp;
unsigned short parmOffset;
tp->datap = outp->data + dataOffset;
return tp;
-}
+}
/* free a tran2 packet */
void smb_FreeTran2Packet(smb_tran2Packet_t *t2p)
free(t2p->parmsp);
if (t2p->datap)
free(t2p->datap);
- }
+ }
+ if (t2p->name) {
+ free(t2p->name);
+ t2p->name = NULL;
+ }
while (t2p->stringsp) {
cm_space_t * ns;
/* We can handle long names */
if (vcp->flags & SMB_VCFLAG_USENT)
smbp->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
-
+
/* now copy important fields from the tran 2 packet */
smbp->com = t2p->com;
smbp->tid = t2p->tid;
smbp->errLow = (unsigned char) (errCode & 0xff);
smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
}
-
+
/* send packet */
smb_SendPacket(vcp, tp);
-}
+}
void smb_SendTran2Packet(smb_vc_t *vcp, smb_tran2Packet_t *t2p, smb_packet_t *tp)
{
smbp->uid = t2p->uid;
smbp->res[0] = t2p->res[0];
+ if (t2p->error_code) {
+ if (vcp->flags & SMB_VCFLAG_STATUS32) {
+ unsigned long NTStatus;
+
+ smb_MapNTError(t2p->error_code, &NTStatus);
+
+ smbp->rcls = (unsigned char) (NTStatus & 0xff);
+ 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_32BIT_STATUS;
+ }
+ else {
+ unsigned short errCode;
+ unsigned char errClass;
+
+ smb_MapCoreError(t2p->error_code, vcp, &errCode, &errClass);
+
+ smbp->rcls = errClass;
+ smbp->errLow = (unsigned char) (errCode & 0xff);
+ smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
+ }
+ }
+
totalLength = 1 + t2p->totalData + t2p->totalParms;
/* now add the core parameters (tran2 info) to the packet */
totalLength += dataAlign;
smb_SetSMBDataLength(tp, totalLength);
-
+
/* next, send the datagram */
smb_SendPacket(vcp, tp);
-}
+}
+
+/* TRANS_SET_NMPIPE_STATE */
+long smb_nmpipeSetState(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+ smb_fid_t *fidp;
+ int fd;
+ int pipeState = 0x0100; /* default */
+ smb_tran2Packet_t *outp = NULL;
+
+ fd = p->pipeParam;
+ if (p->totalParms > 0)
+ pipeState = p->parmsp[0];
+
+ osi_Log2(smb_logp, "smb_nmpipeSetState for fd[%d] with state[0x%x]", fd, pipeState);
+
+ fidp = smb_FindFID(vcp, fd, 0);
+ 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;
+ if (pipeState & 0x0100)
+ fidp->flags |= SMB_FID_MESSAGEMODEPIPE;
+ lock_ReleaseMutex(&fidp->mx);
+
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 0);
+ smb_SendTran2Packet(vcp, outp, op);
+ smb_FreeTran2Packet(outp);
+
+ smb_ReleaseFID(fidp);
+
+ return 0;
+}
+
+long smb_nmpipeTransact(smb_vc_t * vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+ smb_fid_t *fidp;
+ int fd;
+ int is_rpc = 0;
+
+ long code = 0;
+
+ fd = p->pipeParam;
+
+ osi_Log3(smb_logp, "smb_nmpipeTransact for fd[%d] %d bytes in, %d max bytes out",
+ fd, p->totalData, p->maxReturnData);
+
+ fidp = smb_FindFID(vcp, fd, 0);
+ 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;
+ }
+ lock_ReleaseMutex(&fidp->mx);
+
+ if (is_rpc) {
+ code = smb_RPCNmpipeTransact(fidp, vcp, p, op);
+ 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;
+ }
+
+ return code;
+}
/* SMB_COM_TRANSACTION and SMB_COM_TRANSACTION_SECONDARY */
/* We sometimes see 0 word count. What to do? */
if (*inp->wctp == 0) {
- osi_Log0(smb_logp, "Transaction2 word count = 0");
+ osi_Log0(smb_logp, "Transaction2 word count = 0");
LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_ZERO_TRANSACTION_COUNT);
smb_SetSMBDataLength(outp, 0);
totalParms = smb_GetSMBParm(inp, 0);
totalData = smb_GetSMBParm(inp, 1);
-
+
firstPacket = (inp->inCom == 0x25);
-
+
/* find the packet we're reassembling */
lock_ObtainWrite(&smb_globalLock);
asp = smb_FindTran2Packet(vcp, inp);
asp = smb_NewTran2Packet(vcp, inp, totalParms, totalData);
}
lock_ReleaseWrite(&smb_globalLock);
-
+
/* now merge in this latest packet; start by looking up offsets */
if (firstPacket) {
parmDisp = dataDisp = 0;
dataOffset = smb_GetSMBParm(inp, 12);
parmCount = smb_GetSMBParm(inp, 9);
dataCount = smb_GetSMBParm(inp, 11);
+ asp->setupCount = smb_GetSMBParmByte(inp, 13);
asp->maxReturnParms = smb_GetSMBParm(inp, 2);
asp->maxReturnData = smb_GetSMBParm(inp, 3);
osi_Log3(smb_logp, "SMB3 received Trans init packet total data %d, cur data %d, max return data %d",
totalData, dataCount, asp->maxReturnData);
+
+ if (asp->setupCount == 2) {
+ clientchar_t * pname;
+
+ asp->pipeCommand = smb_GetSMBParm(inp, 14);
+ asp->pipeParam = smb_GetSMBParm(inp, 15);
+ pname = smb_ParseString(inp, inp->wctp + 35, NULL, 0);
+ if (pname) {
+ asp->name = cm_ClientStrDup(pname);
+ }
+
+ osi_Log2(smb_logp, " Named Pipe command id [%d] with name [%S]",
+ asp->pipeCommand, osi_LogSaveClientString(smb_logp, asp->name));
+ }
}
else {
parmDisp = smb_GetSMBParm(inp, 4);
osi_Log2(smb_logp, "SMB3 received Trans aux packet parms %d, data %d",
parmCount, dataCount);
- }
+ }
/* now copy the parms and data */
if ( asp->totalParms > 0 && parmCount != 0 )
asp->curParms += parmCount;
/* finally, if we're done, remove the packet from the queue and dispatch it */
- if (asp->totalParms > 0 &&
- asp->curParms > 0 &&
+ if (((asp->totalParms > 0 && asp->curParms > 0)
+ || asp->setupCount == 2) &&
asp->totalData <= asp->curData &&
asp->totalParms <= asp->curParms) {
+
/* we've received it all */
lock_ObtainWrite(&smb_globalLock);
osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
lock_ReleaseWrite(&smb_globalLock);
- /* now dispatch it */
- rapOp = asp->parmsp[0];
+ switch(asp->setupCount) {
+ case 0:
+ { /* RAP */
+ rapOp = asp->parmsp[0];
- if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES && smb_rapDispatchTable[rapOp].procp) {
- osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%p] lana[%d] lsn[%d]",myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
- code = (*smb_rapDispatchTable[rapOp].procp)(vcp, asp, outp);
- osi_Log4(smb_logp,"AFS Server - Dispatch-RAP return code 0x%x vcp[%x] lana[%d] lsn[%d]",code,vcp,vcp->lana,vcp->lsn);
- }
- else {
- osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%p] lana[%d] lsn[%d]", rapOp, vcp, vcp->lana, vcp->lsn);
- code = CM_ERROR_BADOP;
- }
+ if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES &&
+ smb_rapDispatchTable[rapOp].procp) {
+
+ osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%p] lana[%d] lsn[%d]",
+ myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
+
+ code = (*smb_rapDispatchTable[rapOp].procp)(vcp, asp, outp);
+
+ osi_Log4(smb_logp,"AFS Server - Dispatch-RAP return code 0x%x vcp[%x] lana[%d] lsn[%d]",
+ code,vcp,vcp->lana,vcp->lsn);
+ }
+ else {
+ osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%p] lana[%d] lsn[%d]",
+ rapOp, vcp, vcp->lana, vcp->lsn);
+
+ code = CM_ERROR_BADOP;
+ }
+ }
+ break;
+
+ case 2:
+ { /* Named pipe operation */
+ osi_Log2(smb_logp, "Named Pipe: %s with name [%S]",
+ myCrt_NmpipeDispatch(asp->pipeCommand),
+ osi_LogSaveClientString(smb_logp, asp->name));
+
+ code = CM_ERROR_BADOP;
+
+ switch (asp->pipeCommand) {
+ case SMB_TRANS_SET_NMPIPE_STATE:
+ code = smb_nmpipeSetState(vcp, asp, outp);
+ break;
+
+ case SMB_TRANS_RAW_READ_NMPIPE:
+ break;
+
+ case SMB_TRANS_QUERY_NMPIPE_STATE:
+ break;
+
+ case SMB_TRANS_QUERY_NMPIPE_INFO:
+ break;
+
+ case SMB_TRANS_PEEK_NMPIPE:
+ break;
+
+ case SMB_TRANS_TRANSACT_NMPIPE:
+ code = smb_nmpipeTransact(vcp, asp, outp);
+ break;
+
+ case SMB_TRANS_RAW_WRITE_NMPIPE:
+ break;
+
+ case SMB_TRANS_READ_NMPIPE:
+ break;
+
+ case SMB_TRANS_WRITE_NMPIPE:
+ break;
+
+ case SMB_TRANS_WAIT_NMPIPE:
+ break;
+
+ case SMB_TRANS_CALL_NMPIPE:
+ break;
+ }
+ }
+ break;
+
+ default:
+ code = CM_ERROR_BADOP;
+ }
/* if an error is returned, we're supposed to send an error packet,
* otherwise the dispatched function already did the data sending.
return CM_ERROR_STOPNOW;
else
return 0;
-}
+}
/* RAP NetShareEnumRequest */
long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
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);
else {
nSharesRet = nShares;
}
-
+
outp = smb_GetTran2ResponsePacket(vcp, p, op, outParmsTotal, outDataTotal);
/* now for the submounts */
for (i=0; i < rootShares.cShare && cshare < nSharesRet; i++) {
/* in case there are collisions with submounts, submounts have
- higher priority */
+ higher priority */
for (j=0; j < nonrootShares; j++)
if (!cm_stricmp_utf8(shares[j].shi1_netname, rootShares.shares[i].shi0_netname))
break;
-
+
if (j < nonrootShares) {
nShares--; /* uncount */
continue;
infoLevel = *tp++;
bufsize = *tp++;
-
+
totalParam = 6;
if (infoLevel == 0)
} else {
userp = smb_GetTran2User(vcp, p);
if (!userp) {
- osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
+ 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) {
}
totalParams = 6;
-
+
/* infolevel 10 */
totalData = sizeof(*info) + /* info */
MAX_COMPUTERNAME_LENGTH + /* wki10_computername */
totalParams = 6;
- totalData =
+ totalData =
(infoLevel == 0) ? sizeof(smb_rap_server_info_0_t)
: (sizeof(smb_rap_server_info_1_t) + smb_ServerCommentLen);
cstrp = (char *) (info1 + 1);
StringCchCopyA(info1->sv1_name, lengthof(info1->sv1_name), "AFS");
- info1->sv1_type =
+ info1->sv1_type =
SMB_SV_TYPE_SERVER |
SMB_SV_TYPE_NT |
SMB_SV_TYPE_SERVER_NT;
/* We sometimes see 0 word count. What to do? */
if (*inp->wctp == 0) {
- osi_Log0(smb_logp, "Transaction2 word count = 0");
+ osi_Log0(smb_logp, "Transaction2 word count = 0");
LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_ZERO_TRANSACTION_COUNT);
smb_SetSMBDataLength(outp, 0);
totalParms = smb_GetSMBParm(inp, 0);
totalData = smb_GetSMBParm(inp, 1);
-
+
firstPacket = (inp->inCom == 0x32);
-
+
/* find the packet we're reassembling */
lock_ObtainWrite(&smb_globalLock);
asp = smb_FindTran2Packet(vcp, inp);
asp = smb_NewTran2Packet(vcp, inp, totalParms, totalData);
}
lock_ReleaseWrite(&smb_globalLock);
-
+
/* now merge in this latest packet; start by looking up offsets */
if (firstPacket) {
parmDisp = dataDisp = 0;
osi_Log2(smb_logp, "SMB3 received T2 aux packet parms %d, data %d",
parmCount, dataCount);
- }
+ }
/* now copy the parms and data */
if ( asp->totalParms > 0 && parmCount != 0 )
smb_LookupTIDPath(vcp, asp->tid, &treepath);
fidp = smb_FindFID(vcp, inp->fid, 0);
- if (fidp && fidp->NTopen_pathp)
- pathname = fidp->NTopen_pathp;
- else if (inp->stringsp->wdata)
- pathname = inp->stringsp->wdata;
-
- if (fidp && fidp->scp)
- afid = fidp->scp->fid;
+ if (fidp) {
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->NTopen_pathp)
+ pathname = fidp->NTopen_pathp;
+ if (fidp->scp)
+ afid = fidp->scp->fid;
+ } else {
+ if (inp->stringsp->wdata)
+ pathname = inp->stringsp->wdata;
+ }
- afsi_log("Request %s duration %d ms user %S tid \"%S\" path? \"%S\" afid (%d.%d.%d.%d)",
+ afsi_log("Request %s duration %d ms user 0x%x \"%S\" pid 0x%x mid 0x%x tid 0x%x \"%S\" path? \"%S\" afid (%d.%d.%d.%d)",
myCrt_2Dispatch(asp->opcode), newTime - oldTime,
- uidp ? uidp->unp->name : NULL,
+ asp->uid, uidp ? uidp->unp->name : NULL,
+ asp->pid, asp->mid, asp->tid,
treepath,
- pathname,
+ pathname,
afid.cell, afid.volume, afid.vnode, afid.unique);
+ if (fidp)
+ lock_ReleaseMutex(&fidp->mx);
+
if (uidp)
smb_ReleaseUID(uidp);
if (fidp)
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;
clientchar_t *tidPathp;
cm_req_t req;
int created = 0;
+ BOOL is_rpc = FALSE;
+ BOOL is_ipc = FALSE;
smb_InitReq(&req);
scp = NULL;
-
+
extraInfo = (p->parmsp[0] & 1); /* return extra info */
returnEALength = (p->parmsp[0] & 8); /* return extended attr length */
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);
-
+
outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0);
+ code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
+ if (code == CM_ERROR_TIDIPC) {
+ is_ipc = TRUE;
+ osi_Log0(smb_logp, "Tran2Open received IPC TID");
+ }
+
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
- if (lastNamep &&
- (cm_ClientStrCmpI(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
- cm_ClientStrCmpI(lastNamep, _C("\\srvsvc")) == 0 ||
- cm_ClientStrCmpI(lastNamep, _C("\\wkssvc")) == 0 ||
- cm_ClientStrCmpI(lastNamep, _C("\\ipc$")) == 0)) {
+ if (lastNamep &&
+
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
+ (cm_ClientStrCmpI(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
+
+ /* Or an RPC endpoint (is_rpc = TRUE assignment is intentional)*/
+ (is_ipc && MSRPC_IsWellKnownService(lastNamep) && (is_rpc = TRUE)))) {
+
+ unsigned short file_type = 0;
+ unsigned short device_state = 0;
+
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- smb_SetupIoctlFid(fidp, spacep);
+
+ if (is_rpc) {
+ code = smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+ osi_Log2(smb_logp, "smb_ReceiveTran2Open Creating RPC Fid [%d] code [%d]",
+ fidp->fid, code);
+ if (code) {
+ smb_ReleaseFID(fidp);
+ smb_FreeTran2Packet(outp);
+ osi_Log1(smb_logp, "smb_SetupRPCFid() failure code [%d]", code);
+ return code;
+ }
+ } else {
+ smb_SetupIoctlFid(fidp, spacep);
+ osi_Log1(smb_logp, "smb_ReceiveTran2Open Creating IOCTL Fid [%d]", fidp->fid);
+ }
/* copy out remainder of the parms */
parmSlot = 0;
if (extraInfo) {
outp->parmsp[parmSlot++] = 0; /* attrs */
outp->parmsp[parmSlot++] = 0; /* mod time */
- outp->parmsp[parmSlot++] = 0;
+ 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 */
- }
+ outp->parmsp[parmSlot++] = file_type;
+ outp->parmsp[parmSlot++] = device_state;
+ }
/* and the final "always present" stuff */
outp->parmsp[parmSlot++] = 1; /* openAction found existing file */
/* next write out the "unique" ID */
if (returnEALength) {
outp->parmsp[parmSlot++] = 0;
outp->parmsp[parmSlot++] = 0;
- }
-
+ }
+
outp->totalData = 0;
outp->totalParms = parmSlot * 2;
-
+
smb_SendTran2Packet(vcp, outp, op);
-
+
smb_FreeTran2Packet(outp);
/* and clean up fid reference */
return 0;
}
+#ifndef DFS_SUPPORT
+ if (is_ipc) {
+ osi_Log1(smb_logp, "Tran2Open rejecting IPC TID vcp %p", vcp);
+ smb_FreeTran2Packet(outp);
+ return CM_ERROR_BADFD;
+ }
+#endif
+
if (!cm_IsValidClientString(pathp)) {
#ifdef DEBUG
clientchar_t * hexp;
hexp = osi_HexifyString( asciip );
DEBUG_EVENT2("AFS","T2Open H[%s] A[%s]", hexp, asciip);
free(hexp);
- }
+ }
#endif
userp = smb_GetTran2User(vcp, p);
return CM_ERROR_BADSMB;
}
- code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
- if (code == CM_ERROR_TIDIPC) {
- /* Attempt to use a TID allocated for IPC. The client
- * is probably looking for DCE RPC end points which we
- * don't support OR it could be looking to make a DFS
- * referral request.
- */
- osi_Log0(smb_logp, "Tran2Open received IPC TID");
-#ifndef DFS_SUPPORT
- cm_ReleaseUser(userp);
- smb_FreeTran2Packet(outp);
- return CM_ERROR_NOSUCHPATH;
-#endif
- }
-
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) {
smb_FreeTran2Packet(outp);
return code;
}
-
+
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp,
if ( WANTS_DFS_PATHNAMES(p) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
* and truncate the file if we find it, otherwise we create the
* file.
*/
- if (!lastNamep)
+ if (!lastNamep)
lastNamep = pathp;
- else
+ else
lastNamep++;
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
&req, &scp);
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);
if ( WANTS_DFS_PATHNAMES(p) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ 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
* scp. Otherwise, we have to create it.
*/
if (code == 0) {
code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
if (code) {
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
if (excl) {
/* oops, file shouldn't be there */
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
setAttr.length.HighPart = 0;
code = cm_SetAttr(scp, &setAttr, userp, &req);
openAction = 3; /* truncated existing file */
- }
- else
+ }
+ else
openAction = 1; /* found existing file */
}
else if (!(openFun & 0x10)) {
/* don't create if not found */
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
osi_assertx(scp == NULL, "null cm_scache_t");
cm_ReleaseUser(userp);
osi_assertx(dscp != NULL && scp == NULL, "null dsc || non-null sc");
openAction = 2; /* created file */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
- smb_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
+ cm_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
+ smb_SetInitialModeBitsForFile(attributes, &setAttr);
+
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0) {
created = 1;
if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
+ FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
dscp, lastNamep, NULL, TRUE);
} else if (!excl && code == CM_ERROR_EXISTS) {
/* not an exclusive create, and someone else tried
setAttr.length.HighPart = 0;
code = cm_SetAttr(scp, &setAttr, userp,
&req);
- }
+ }
} /* lookup succeeded */
}
}
-
+
/* we don't need this any longer */
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
if (code) {
/* something went wrong creating or truncating the file */
- if (scp)
+ if (scp)
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
return code;
}
-
+
/* make sure we're about to open a file */
if (scp->fileType != CM_SCACHETYPE_FILE) {
code = 0;
/* now all we have to do is open the file itself */
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
osi_assertx(fidp, "null smb_fid_t");
-
+
cm_HoldUser(userp);
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
lock_ObtainWrite(&scp->rw);
scp->flags |= CM_SCACHEFLAG_SMB_FID;
lock_ReleaseWrite(&scp->rw);
-
+
/* and the user */
fidp->userp = userp;
-
+
/* compute open mode */
- if (openMode != 1)
+ if (openMode != 1)
fidp->flags |= SMB_FID_OPENREAD_LISTDIR;
if (openMode == 1 || openMode == 2)
fidp->flags |= SMB_FID_OPENWRITE;
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
-
+
cm_Open(scp, 0, userp);
/* copy out remainder of the parms */
lock_ObtainRead(&scp->rw);
if (extraInfo) {
outp->parmsp[parmSlot++] = smb_Attributes(scp);
- smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+ cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
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++] = 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;
/* next write out the "unique" ID */
- outp->parmsp[parmSlot++] = (unsigned short) (scp->fid.vnode & 0xffff);
- outp->parmsp[parmSlot++] = (unsigned short) (scp->fid.volume & 0xffff);
- outp->parmsp[parmSlot++] = 0;
+ 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;
- outp->parmsp[parmSlot++] = 0;
- }
+ outp->parmsp[parmSlot++] = 0;
+ outp->parmsp[parmSlot++] = 0;
+ }
lock_ReleaseRead(&scp->rw);
outp->totalData = 0; /* total # of data bytes */
outp->totalParms = parmSlot * 2; /* shorts are two bytes */
cm_ReleaseUser(userp);
/* leave scp held since we put it in fidp->scp */
return 0;
-}
+}
long smb_ReceiveTran2QFSInfoFid(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
{
infolevel = p->parmsp[0];
fid = p->parmsp[1];
osi_Log2(smb_logp, "T2 QFSInfoFid InfoLevel 0x%x fid 0x%x - NOT_SUPPORTED", infolevel, fid);
-
+
return CM_ERROR_BAD_LEVEL;
}
smb_tran2QFSInfo_t qi;
int responseSize;
size_t sz = 0;
-
+
osi_Log1(smb_logp, "T2 QFSInfo type 0x%x", p->parmsp[0]);
switch (p->parmsp[0]) {
- case SMB_INFO_ALLOCATION:
+ case SMB_INFO_ALLOCATION:
/* alloc info */
- responseSize = sizeof(qi.u.allocInfo);
+ responseSize = sizeof(qi.u.allocInfo);
qi.u.allocInfo.FSID = 0;
qi.u.allocInfo.sectorsPerAllocUnit = 1;
qi.u.allocInfo.bytesPerSector = 1024;
break;
- case SMB_INFO_VOLUME:
+ case SMB_INFO_VOLUME:
/* volume info */
qi.u.volumeInfo.vsn = 1234; /* Volume serial number */
qi.u.volumeInfo.vnCount = 3; /* Number of characters in label (AFS\0)*/
responseSize = sizeof(unsigned long) + sizeof(char) + max(12, sz);
break;
- case SMB_QUERY_FS_VOLUME_INFO:
+ case SMB_QUERY_FS_VOLUME_INFO:
/* FS volume info */
responseSize = sizeof(qi.u.FSvolumeInfo);
memcpy(qi.u.FSvolumeInfo.label, L"AFS", sizeof(L"AFS"));
break;
- case SMB_QUERY_FS_SIZE_INFO:
+ case SMB_QUERY_FS_SIZE_INFO:
/* FS size info */
- responseSize = sizeof(qi.u.FSsizeInfo);
+ responseSize = sizeof(qi.u.FSsizeInfo);
qi.u.FSsizeInfo.totalAllocUnits.HighPart = 0;
qi.u.FSsizeInfo.totalAllocUnits.LowPart= 0x7fffffff;
qi.u.FSsizeInfo.bytesPerSector = 1024;
break;
- case SMB_QUERY_FS_DEVICE_INFO:
+ case SMB_QUERY_FS_DEVICE_INFO:
/* FS device info */
- responseSize = sizeof(qi.u.FSdeviceInfo);
+ responseSize = sizeof(qi.u.FSdeviceInfo);
qi.u.FSdeviceInfo.devType = 0x14; /* network file system */
qi.u.FSdeviceInfo.characteristics = 0x50; /* remote, virtual */
break;
- case SMB_QUERY_FS_ATTRIBUTE_INFO:
+ case SMB_QUERY_FS_ATTRIBUTE_INFO:
/* FS attribute info */
/* attributes, defined in WINNT.H:
* FILE_CASE_SENSITIVE_SEARCH 0x1
* FILE_CASE_PRESERVED_NAMES 0x2
+ * FILE_UNICODE_ON_DISK 0x4
* FILE_VOLUME_QUOTAS 0x10
* <no name defined> 0x4000
* If bit 0x4000 is not set, Windows 95 thinks
qi.u.FSattributeInfo.attributes = 0x4003;
/* The maxCompLength is supposed to be in bytes */
#ifdef SMB_UNICODE
- if ((vcp->flags & SMB_VCFLAG_USEUNICODE) == SMB_VCFLAG_USEUNICODE)
- qi.u.FSattributeInfo.maxCompLength = MAX_PATH * sizeof(wchar_t);
- else {
-#endif
- qi.u.FSattributeInfo.maxCompLength = MAX_PATH;
-#ifdef SMB_UNICODE
- }
+ qi.u.FSattributeInfo.attributes |= 0x04;
#endif
+ qi.u.FSattributeInfo.maxCompLength = 255;
smb_UnparseString(op, qi.u.FSattributeInfo.FSname, _C("AFS"), &sz, SMB_STRF_IGNORENUL);
qi.u.FSattributeInfo.FSnameLength = sz;
case SMB_INFO_UNIX: /* CIFS Unix Info */
case SMB_INFO_MACOS: /* Mac FS Info */
- default:
+ default:
return CM_ERROR_BADOP;
- }
-
+ }
+
outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, responseSize);
-
+
/* copy out return data, and set corresponding sizes */
outp->totalParms = 0;
outp->totalData = responseSize;
unsigned int vnode;
clientchar_t *shortName;
size_t shortNameLen;
-};
+};
int cm_GetShortNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *vrockp,
osi_hyper_t *offp)
-{
+{
struct smb_ShortNameRock *rockp;
normchar_t normName[MAX_PATH];
clientchar_t *shortNameEnd;
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);
- if (code)
+ if (code)
return code;
#ifdef DFS_SUPPORT
smb_InitReq(&req);
infoLevel = p->parmsp[0];
- if (infoLevel == SMB_INFO_IS_NAME_VALID)
+ if (infoLevel == SMB_INFO_IS_NAME_VALID)
responseSize = 0;
- else if (infoLevel == SMB_INFO_STANDARD)
+ else if (infoLevel == SMB_INFO_STANDARD)
responseSize = sizeof(qpi.u.QPstandardInfo);
- else if (infoLevel == SMB_INFO_QUERY_EA_SIZE)
+ else if (infoLevel == SMB_INFO_QUERY_EA_SIZE)
responseSize = sizeof(qpi.u.QPeaSizeInfo);
else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO)
responseSize = sizeof(qpi.u.QPfileBasicInfo);
responseSize = sizeof(qpi.u.QPfileStandardInfo);
else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
responseSize = sizeof(qpi.u.QPfileEaInfo);
- else if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
+ else if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
responseSize = sizeof(qpi.u.QPfileNameInfo);
- else if (infoLevel == SMB_QUERY_FILE_ALL_INFO)
+ else if (infoLevel == SMB_QUERY_FILE_ALL_INFO)
responseSize = sizeof(qpi.u.QPfileAllInfo);
- else if (infoLevel == SMB_QUERY_FILE_ALT_NAME_INFO)
+ 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*
* being asked to verify anything about the state of any parent dirs.
smb_SendTran2Packet(vcp, outp, opx);
smb_FreeTran2Packet(outp);
return 0;
- }
-
+ }
+
userp = smb_GetTran2User(vcp, p);
if (!userp) {
osi_Log1(smb_logp, "ReceiveTran2QPathInfo unable to resolve user [%d]", p->uid);
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,
if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
- code = CM_ERROR_BADSHARENAME;
+ code = CM_ERROR_NOSUCHPATH;
} else
#endif /* DFS_SUPPORT */
if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
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);
if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
- code = CM_ERROR_BADSHARENAME;
+ code = CM_ERROR_NOSUCHPATH;
smb_SendTran2Error(vcp, p, opx, code);
smb_FreeTran2Packet(outp);
return 0;
goto done;
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-
+
lock_ConvertWToR(&scp->rw);
scp_rw_held = 1;
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) {
- smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+ cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
qpi.u.QPstandardInfo.creationDateTime = dosTime;
qpi.u.QPstandardInfo.lastAccessDateTime = dosTime;
qpi.u.QPstandardInfo.lastWriteDateTime = dosTime;
qpi.u.QPstandardInfo.eaSize = 0;
}
else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
qpi.u.QPfileBasicInfo.creationTime = ft;
qpi.u.QPfileBasicInfo.lastAccessTime = ft;
qpi.u.QPfileBasicInfo.lastWriteTime = ft;
}
else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
smb_fid_t * fidp;
-
+
lock_ReleaseRead(&scp->rw);
scp_rw_held = 0;
fidp = smb_FindFIDByScache(vcp, scp);
qpi.u.QPfileStandardInfo.allocationSize = scp->length;
qpi.u.QPfileStandardInfo.endOfFile = scp->length;
qpi.u.QPfileStandardInfo.numberOfLinks = scp->linkCount;
- qpi.u.QPfileStandardInfo.directory =
+ qpi.u.QPfileStandardInfo.directory =
((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
qpi.u.QPfileEaInfo.eaSize = 0;
}
else if (infoLevel == SMB_QUERY_FILE_ALL_INFO) {
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ 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;
qpi.u.QPfileAllInfo.lastWriteTime = ft;
qpi.u.QPfileAllInfo.endOfFile = scp->length;
qpi.u.QPfileAllInfo.numberOfLinks = scp->linkCount;
qpi.u.QPfileAllInfo.deletePending = 0;
- qpi.u.QPfileAllInfo.directory =
+ qpi.u.QPfileAllInfo.directory =
((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:
return CM_ERROR_BADOP;
#else
long code = 0;
- smb_fid_t *fidp;
unsigned short infoLevel;
clientchar_t * pathp;
smb_tran2Packet_t *outp;
infoLevel = p->parmsp[0];
osi_Log1(smb_logp,"ReceiveTran2SetPathInfo type 0x%x", infoLevel);
- if (infoLevel != SMB_INFO_STANDARD &&
+ 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,
+ smb_SendTran2Error(vcp, p, opx,
infoLevel == SMB_INFO_QUERY_ALL_EAS ? CM_ERROR_EAS_NOT_SUPPORTED : CM_ERROR_BAD_LEVEL);
return 0;
}
osi_Log1(smb_logp,"ReceiveTran2SetPathInfo unable to resolve user [%d]", p->uid);
code = CM_ERROR_BADSMB;
goto done;
- }
+ }
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if (code == CM_ERROR_TIDIPC) {
/* Attempt to use a TID allocated for IPC. The client
* is probably looking for DCE RPC end points which we
* don't support OR it could be looking to make a DFS
- * referral request.
+ * referral request.
*/
osi_Log0(smb_logp, "Tran2Open received IPC TID");
cm_ReleaseUser(userp);
*/
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,
if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
- code = CM_ERROR_BADSHARENAME;
+ code = CM_ERROR_NOSUCHPATH;
} else
#endif /* DFS_SUPPORT */
if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
cm_FreeSpace(spacep);
}
- /* now do namei and stat, and copy out the info */
- code = cm_NameI(cm_data.rootSCachep, pathp,
- CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
- if (code) {
- cm_ReleaseUser(userp);
- smb_SendTran2Error(vcp, p, opx, code);
- return 0;
- }
-
- fidp = smb_FindFIDByScache(vcp, scp);
- if (!fidp) {
- cm_ReleaseSCache(scp);
- cm_ReleaseUser(userp);
- smb_SendTran2Error(vcp, p, opx, code);
- return 0;
+ 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);
}
- lock_ObtainMutex(&fidp->mx);
- if (!(fidp->flags & SMB_FID_OPENWRITE)) {
- lock_ReleaseMutex(&fidp->mx);
- cm_ReleaseSCache(scp);
- smb_ReleaseFID(fidp);
+ if (code) {
cm_ReleaseUser(userp);
- smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOACCESS);
+ smb_SendTran2Error(vcp, p, opx, code);
return 0;
}
- lock_ReleaseMutex(&fidp->mx);
outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, 0);
}
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- lock_ReleaseWrite(&scp->rw);
- lock_ObtainMutex(&fidp->mx);
- lock_ObtainRead(&scp->rw);
-
/* prepare for setattr call */
attr.mask = CM_ATTRMASK_LENGTH;
attr.length.LowPart = spi->u.QPstandardInfo.dataSize;
attr.length.HighPart = 0;
if (spi->u.QPstandardInfo.lastWriteDateTime != 0) {
- smb_UnixTimeFromSearchTime(&attr.clientModTime, spi->u.QPstandardInfo.lastWriteDateTime);
+ cm_UnixTimeFromSearchTime(&attr.clientModTime, spi->u.QPstandardInfo.lastWriteDateTime);
attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
- fidp->flags |= SMB_FID_MTIMESETDONE;
}
-
+
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;
}
}
lock_ReleaseRead(&scp->rw);
- lock_ReleaseMutex(&fidp->mx);
/* call setattr */
if (attr.mask)
code = cm_SetAttr(scp, &attr, userp, &req);
else
code = 0;
- }
+ }
else if (infoLevel == SMB_INFO_QUERY_ALL_EAS) {
/* we don't support EAs */
code = CM_ERROR_EAS_NOT_SUPPORTED;
- }
+ }
done:
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
- smb_ReleaseFID(fidp);
- if (code == 0)
+ if (code == 0)
smb_SendTran2Packet(vcp, outp, opx);
- else
+ else
smb_SendTran2Error(vcp, p, opx, code);
smb_FreeTran2Packet(outp);
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;
}
+ lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHFILE);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return 0;
}
+ lock_ReleaseMutex(&fidp->mx);
infoLevel = p->parmsp[1];
- if (infoLevel == SMB_QUERY_FILE_BASIC_INFO)
+ if (infoLevel == SMB_QUERY_FILE_BASIC_INFO)
responseSize = sizeof(qfi.u.QFbasicInfo);
- else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO)
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO)
responseSize = sizeof(qfi.u.QFstandardInfo);
else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
responseSize = sizeof(qfi.u.QFeaInfo);
- else if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
+ 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) {
osi_Log1(smb_logp, "ReceiveTran2QFileInfo unable to resolve user [%d]", p->uid);
code = CM_ERROR_BADSMB;
goto done;
- }
+ }
lock_ObtainMutex(&fidp->mx);
delonclose = fidp->flags & SMB_FID_DELONCLOSE;
lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code)
+ if (code)
goto done;
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
* Marshall the output data.
*/
if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
qfi.u.QFbasicInfo.creationTime = ft;
qfi.u.QFbasicInfo.lastAccessTime = ft;
qfi.u.QFbasicInfo.lastWriteTime = ft;
qfi.u.QFstandardInfo.endOfFile = scp->length;
qfi.u.QFstandardInfo.numberOfLinks = scp->linkCount;
qfi.u.QFstandardInfo.deletePending = (delonclose ? 1 : 0);
- qfi.u.QFstandardInfo.directory =
+ qfi.u.QFstandardInfo.directory =
((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
scp->fileType == CM_SCACHETYPE_INVALID)? 1 : 0);
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:
smb_FreeTran2Packet(outp);
return 0;
-}
+}
/* TRANS2_SET_FILE_INFORMATION */
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;
}
- if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
- smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHFILE);
- smb_CloseFID(vcp, fidp, NULL, 0);
- smb_ReleaseFID(fidp);
- 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);
}
lock_ObtainMutex(&fidp->mx);
- if (infoLevel == SMB_SET_FILE_DISPOSITION_INFO &&
+ if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHFILE);
+ smb_CloseFID(vcp, fidp, NULL, 0);
+ smb_ReleaseFID(fidp);
+ return 0;
+ }
+
+ if (infoLevel == SMB_SET_FILE_DISPOSITION_INFO &&
!(fidp->flags & SMB_FID_OPENDELETE)) {
- osi_Log3(smb_logp,"smb_ReceiveTran2SetFileInfo !SMB_FID_OPENDELETE fidp 0x%p scp 0x%p fidp->flags 0x%x",
+ osi_Log3(smb_logp,"smb_ReceiveTran2SetFileInfo !SMB_FID_OPENDELETE fidp 0x%p scp 0x%p fidp->flags 0x%x",
fidp, fidp->scp, fidp->flags);
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOACCESS);
return 0;
}
- if ((infoLevel == SMB_SET_FILE_ALLOCATION_INFO ||
+ if ((infoLevel == SMB_SET_FILE_ALLOCATION_INFO ||
infoLevel == SMB_SET_FILE_END_OF_FILE_INFO)
&& !(fidp->flags & SMB_FID_OPENWRITE)) {
- osi_Log3(smb_logp,"smb_ReceiveTran2SetFileInfo !SMB_FID_OPENWRITE fidp 0x%p scp 0x%p fidp->flags 0x%x",
+ osi_Log3(smb_logp,"smb_ReceiveTran2SetFileInfo !SMB_FID_OPENWRITE fidp 0x%p scp 0x%p fidp->flags 0x%x",
fidp, fidp->scp, fidp->flags);
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
osi_Log1(smb_logp,"ReceiveTran2SetFileInfo unable to resolve user [%d]", p->uid);
code = CM_ERROR_BADSMB;
goto done;
- }
+ }
if (infoLevel == SMB_SET_FILE_BASIC_INFO) {
FILETIME lastMod;
attr.mask = 0;
lastMod = sfi->u.QFbasicInfo.lastWriteTime;
- /* when called as result of move a b, lastMod is (-1, -1).
+ /* when called as result of move a b, lastMod is (-1, -1).
* If the check for -1 is not present, timestamp
* of the resulting file will be 1969 (-1)
*/
- if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) &&
+ if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) &&
lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
- smb_UnixTimeFromLargeSearchTime(&attr.clientModTime, &lastMod);
+ cm_UnixTimeFromLargeSearchTime(&attr.clientModTime, &lastMod);
fidp->flags |= SMB_FID_MTIMESETDONE;
}
-
+
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;
}
else if (infoLevel == SMB_SET_FILE_DISPOSITION_INFO) {
int delflag = *((char *)(p->datap));
- osi_Log3(smb_logp,"smb_ReceiveTran2SetFileInfo Delete? %d fidp 0x%p scp 0x%p",
+ osi_Log3(smb_logp,"smb_ReceiveTran2SetFileInfo Delete? %d fidp 0x%p scp 0x%p",
delflag, fidp, scp);
if (*((char *)(p->datap))) { /* File is Deleted */
code = cm_CheckNTDelete(fidp->NTopen_dscp, scp, userp,
fidp->flags |= SMB_FID_DELONCLOSE;
lock_ReleaseMutex(&fidp->mx);
} else {
- osi_Log3(smb_logp,"smb_ReceiveTran2SetFileInfo CheckNTDelete fidp 0x%p scp 0x%p code 0x%x",
+ osi_Log3(smb_logp,"smb_ReceiveTran2SetFileInfo CheckNTDelete fidp 0x%p scp 0x%p code 0x%x",
fidp, scp, code);
}
- }
- else {
+ }
+ else {
code = 0;
lock_ObtainMutex(&fidp->mx);
fidp->flags &= ~SMB_FID_DELONCLOSE;
lock_ReleaseMutex(&fidp->mx);
}
- }
+ }
else if (infoLevel == SMB_SET_FILE_ALLOCATION_INFO ||
infoLevel == SMB_SET_FILE_END_OF_FILE_INFO) {
LARGE_INTEGER size = *((LARGE_INTEGER *)(p->datap));
attr.length.LowPart = size.LowPart;
attr.length.HighPart = size.HighPart;
code = cm_SetAttr(scp, &attr, userp, &req);
- }
+ }
done:
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
- if (code == 0)
+ if (code == 0)
smb_SendTran2Packet(vcp, outp, opx);
- else
+ else
smb_SendTran2Error(vcp, p, opx, code);
smb_FreeTran2Packet(outp);
}
/* TRANS2_FSCTL */
-long
+long
smb_ReceiveTran2FSCTL(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
{
osi_Log0(smb_logp,"ReceiveTran2FSCTL - NOT_SUPPORTED");
}
/* TRANS2_IOCTL2 */
-long
+long
smb_ReceiveTran2IOCTL(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
{
osi_Log0(smb_logp,"ReceiveTran2IOCTL - NOT_SUPPORTED");
}
/* TRANS2_FIND_NOTIFY_FIRST */
-long
+long
smb_ReceiveTran2FindNotifyFirst(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
{
osi_Log0(smb_logp,"ReceiveTran2FindNotifyFirst - NOT_SUPPORTED");
}
/* TRANS2_FIND_NOTIFY_NEXT */
-long
+long
smb_ReceiveTran2FindNotifyNext(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
{
osi_Log0(smb_logp,"ReceiveTran2FindNotifyNext - NOT_SUPPORTED");
}
/* TRANS2_CREATE_DIRECTORY */
-long
+long
smb_ReceiveTran2CreateDirectory(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
{
osi_Log0(smb_logp,"ReceiveTran2CreateDirectory - NOT_SUPPORTED");
}
/* TRANS2_SESSION_SETUP */
-long
+long
smb_ReceiveTran2SessionSetup(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
{
osi_Log0(smb_logp,"ReceiveTran2SessionSetup - NOT_SUPPORTED");
};
/* TRANS2_GET_DFS_REFERRAL */
-long
+long
smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
{
/* This is a UNICODE only request (bit15 of Flags2) */
GetCPInfo(CP_ACP, &CodePageInfo);
cm_Utf16ToClientString(&p->parmsp[1], -1, requestFileName, lengthof(requestFileName));
- osi_Log2(smb_logp,"ReceiveTran2GetDfsReferral [%d][%S]",
+ osi_Log2(smb_logp,"ReceiveTran2GetDfsReferral [%d][%S]",
maxReferralLevel, osi_LogSaveClientString(smb_logp, requestFileName));
nbnLen = (int)cm_ClientStrLen(cm_NetbiosNameC);
if (reqLen > nbnLen + 2 && requestFileName[0] == '\\' &&
!cm_ClientStrCmpNI(cm_NetbiosNameC, &requestFileName[1], nbnLen) &&
- requestFileName[nbnLen+1] == '\\')
+ requestFileName[nbnLen+1] == '\\')
{
int found = 0;
osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
code = CM_ERROR_BADSMB;
goto done;
- }
-
- /*
- * We have a requested path. Check to see if it is something
+ }
+
+ /*
+ * We have a requested path. Check to see if it is something
* we know about.
- *
- * But be careful because the name that we might be searching
- * for might be a known name with the final character stripped
- * off. If we
+ *
+ * But be careful because the name that we might be searching
+ * 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) {
+ if (code == 0 ||
+ code == CM_ERROR_ALLDOWN ||
+ code == CM_ERROR_ALLBUSY ||
+ code == CM_ERROR_ALLOFFLINE ||
+ code == CM_ERROR_NOSUCHCELL ||
+ code == CM_ERROR_NOSUCHVOLUME ||
+ code == CM_ERROR_NOACCESS) {
/* Yes it is. */
found = 1;
cm_ClientStrCpy(referralPath, lengthof(referralPath), requestFileName);
clientchar_t temp[1024];
clientchar_t pathName[1024];
clientchar_t *lastComponent;
- /*
+ /*
* we have a msdfs link somewhere in the path
* we should figure out where in the path the link is.
* and return it.
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 = *p;
}
*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);
}
}
}
-
+
if (found)
{
USHORT * sp;
sp[idx++] = 0x03; /* flags */
#ifdef DFS_VERSION_1
sp[idx++] = 1; /* Version Number */
- sp[idx++] = refLen + 4; /* Referral Size */
+ sp[idx++] = refLen + 4; /* Referral Size */
sp[idx++] = 1; /* Type = SMB Server */
sp[idx++] = 0; /* Do not strip path consumed */
for ( i=0;i<=refLen; i++ )
for ( i=0;i<=refLen; i++ )
sp[i+idx] = referralPath[i];
#endif
- }
+ } else {
+ code = CM_ERROR_NOSUCHPATH;
+ }
} else {
code = CM_ERROR_NOSUCHPATH;
}
-
+
done:
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
if (userp)
cm_ReleaseUser(userp);
- if (code == 0)
+ if (code == 0)
smb_SendTran2Packet(vcp, outp, op);
- else
+ else
smb_SendTran2Error(vcp, p, op, code);
if (outp)
smb_FreeTran2Packet(outp);
-
+
return 0;
#else /* DFS_SUPPORT */
- osi_Log0(smb_logp,"ReceiveTran2GetDfsReferral - NOT_SUPPORTED");
+ osi_Log0(smb_logp,"ReceiveTran2GetDfsReferral - NOT_SUPPORTED");
return CM_ERROR_NOSUCHDEVICE;
#endif /* DFS_SUPPORT */
}
/* TRANS2_REPORT_DFS_INCONSISTENCY */
-long
+long
smb_ReceiveTran2ReportDFSInconsistency(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
{
/* This is a UNICODE only request (bit15 of Flags2) */
/* There is nothing we can do about this operation. The client is going to
* tell us that there is a Version 1 Referral Element for which there is a DFS Error.
- * Unfortunately, there is really nothing we can do about it other then log it
+ * Unfortunately, there is really nothing we can do about it other then log it
* somewhere. Even then I don't think there is anything for us to do.
* So let's return an error value.
*/
return CM_ERROR_BADOP;
}
-static long
-smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp,
- clientchar_t * tidPathp, clientchar_t * relPathp,
+static long
+smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp,
+ clientchar_t * tidPathp, clientchar_t * relPathp,
int infoLevel, cm_user_t *userp, cm_req_t *reqp)
{
long code = 0;
lock_ObtainWrite(&dscp->rw);
code = cm_SyncOp(dscp, NULL, userp, reqp, PRSFS_READ,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code == 0)
+ if (code == 0)
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ReleaseWrite(&dscp->rw);
if (code == CM_ERROR_NOACCESS) {
memset(bsp, 0, sizeof(cm_bulkStat_t));
- for (patchp = *dirPatchespp, count=0;
- patchp;
+ for (patchp = *dirPatchespp, count=0;
+ patchp;
patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
cm_scache_t *tscp = NULL;
int i;
-
+
+ /* Do not look for a cm_scache_t or bulkstat an ioctl entry */
+ if (patchp->flags & SMB_DIRLISTPATCH_IOCTL)
+ continue;
+
code = cm_GetSCache(&patchp->fid, &tscp, userp, reqp);
if (code == 0) {
if (lock_TryWrite(&tscp->rw)) {
if (dscp->fid.cell == AFS_FAKE_ROOT_CELL_ID && dscp->fid.volume == AFS_FAKE_ROOT_VOL_ID) {
code = cm_SyncOp(tscp, NULL, userp, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code == 0)
+ if (code == 0)
cm_SyncOpDone(tscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ReleaseWrite(&tscp->rw);
free(bsp);
}
- for( patchp = *dirPatchespp;
- patchp;
+ for( patchp = *dirPatchespp;
+ patchp;
patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
cm_ClientStrPrintfN(path, lengthof(path),_C("%s\\%S"),
relPathp ? relPathp : _C(""), patchp->dep->name);
reqp->relPathp = path;
reqp->tidPathp = tidPathp;
+ if (patchp->flags & SMB_DIRLISTPATCH_IOCTL) {
+ /* Plug in fake timestamps. A time stamp of 0 causes 'invalid parameter'
+ errors in the client. */
+ if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) {
+ smb_V3FileAttrsLong * fa = (smb_V3FileAttrsLong *) patchp->dptr;
+
+ /* 1969-12-31 23:59:59 +00 */
+ ft.dwHighDateTime = 0x19DB200;
+ ft.dwLowDateTime = 0x5BB78980;
+
+ /* copy to Creation Time */
+ fa->creationTime = ft;
+ fa->lastAccessTime = ft;
+ fa->lastWriteTime = ft;
+ fa->lastChangeTime = ft;
+ fa->extFileAttributes = SMB_ATTR_SYSTEM | SMB_ATTR_HIDDEN;
+ } else {
+ smb_V3FileAttrsShort * fa = (smb_V3FileAttrsShort *) patchp->dptr;
+
+ /* 1969-12-31 23:59:58 +00*/
+ dosTime = 0xEBBFBF7D;
+
+ fa->creationDateTime = MAKELONG(HIWORD(dosTime),LOWORD(dosTime));
+ fa->lastAccessDateTime = fa->creationDateTime;
+ fa->lastWriteDateTime = fa->creationDateTime;
+ fa->attributes = SMB_ATTR_SYSTEM|SMB_ATTR_HIDDEN;
+ }
+ continue;
+ }
+
code = cm_GetSCache(&patchp->fid, &scp, userp, reqp);
reqp->relPathp = reqp->tidPathp = NULL;
- if (code)
+ if (code)
continue;
lock_ObtainWrite(&scp->rw);
break;
default:
/* if we get here we either have a normal file
- * or we have a file for which we have never
+ * or we have a file for which we have never
* received status info. In this case, we can
* check the even/odd value of the entry's vnode.
* odd means it is to be treated as a directory
break;
default:
/* if we get here we either have a normal file
- * or we have a file for which we have never
+ * or we have a file for which we have never
* received status info. In this case, we can
* check the even/odd value of the entry's vnode.
* even means it is to be treated as a directory
/* merge in hidden (dot file) attribute */
if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
fa->attributes |= SMB_ATTR_HIDDEN;
- }
+ }
}
-
+
cm_ReleaseSCache(scp);
continue;
}
-
+
/* now watch for a symlink */
code = 0;
while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
smb_V3FileAttrsLong * fa = (smb_V3FileAttrsLong *) patchp->dptr;
/* get filetime */
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
fa->creationTime = ft;
fa->lastAccessTime = ft;
/* Copy attributes */
lattr = smb_ExtAttributes(scp);
- if ((code == CM_ERROR_NOSUCHPATH &&
- (scp->fileType == CM_SCACHETYPE_SYMLINK &&
+ if ((code == CM_ERROR_NOSUCHPATH &&
+ (scp->fileType == CM_SCACHETYPE_SYMLINK &&
cm_TargetPerceivedAsDirectory(scp->mountPointStringp))) ||
code == CM_ERROR_PATH_NOT_COVERED && scp->fileType == CM_SCACHETYPE_DFSLINK) {
if (lattr == SMB_ATTR_NORMAL)
smb_V3FileAttrsShort * fa = (smb_V3FileAttrsShort *) patchp->dptr;
/* get dos time */
- smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+ cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
fa->creationDateTime = MAKELONG(HIWORD(dosTime), LOWORD(dosTime));
fa->lastAccessDateTime = fa->creationDateTime;
lock_ReleaseRead(&scp->rw);
cm_ReleaseSCache(scp);
}
-
+
/* now free the patches */
for (patchp = *dirPatchespp; patchp; patchp = npatchp) {
npatchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q);
free(patchp);
}
-
+
/* and mark the list as empty */
*dirPatchespp = NULL;
return code;
}
-/* smb_ReceiveTran2SearchDir implements both
+/* smb_ReceiveTran2SearchDir implements both
* Tran2_Find_First and Tran2_Find_Next
*/
#define TRAN2_FIND_FLAG_CLOSE_SEARCH 0x01
application is using FindFirst(Ex) to get information about a
single file or directory. It will attempt to do a single lookup.
If that fails, then smb_ReceiveTran2SearchDir() will fall back to
- the usual mechanism.
-
+ the usual mechanism.
+
This function will return either CM_ERROR_NOSUCHFILE or SUCCESS.
TRANS2_FIND_FIRST2 and TRANS2_FIND_NEXT2
size_t ohbytes; /* # of bytes, except file name */
size_t onbytes; /* # of bytes in name, incl. term. null */
cm_scache_t *scp = NULL;
- cm_scache_t *targetscp = NULL;
+ cm_scache_t *targetScp = NULL;
cm_user_t *userp = NULL;
char *op; /* output data ptr */
char *origOp; /* original value of op */
smb_tran2Packet_t *outp; /* response packet */
clientchar_t *tidPathp = 0;
int align;
- clientchar_t shortName[13]; /* 8.3 name if needed */
+ clientchar_t shortName[13]; /* 8.3 name if needed */
int NeedShortName;
clientchar_t *shortNameEnd;
cm_dirEntry_t * dep = NULL;
char * s;
void * attrp = NULL;
smb_tran2Find_t * fp;
+ int afs_ioctl = 0; /* is this query for _._AFS_IOCTL_._? */
+ cm_dirFid_t dfid;
smb_InitReq(&req);
pathp = smb_ParseStringT2Parm(p, (char *) &(p->parmsp[6]), NULL, SMB_STRF_ANSIPATH);
nextCookie = 0;
maskp = cm_ClientStrRChr(pathp, '\\');
- if (maskp == NULL)
+ if (maskp == NULL)
maskp = pathp;
- else
+ else
maskp++; /* skip over backslash */
/* track if this is likely to match a lot of entries */
osi_Log4(smb_logp,
"smb_T2SearchDirSingle attr 0x%x, info level 0x%x, max count %d, flags 0x%x",
attribute, infoLevel, maxCount, searchFlags);
-
+
if (ohbytes == 0) {
osi_Log1(smb_logp, "Unsupported InfoLevel 0x%x", infoLevel);
return CM_ERROR_INVAL;
osi_Log2(smb_logp, "T2SDSingle search dir count %d [%S]",
maxCount, osi_LogSaveClientString(smb_logp, pathp));
-
+
/* bail out if request looks bad */
if (!pathp) {
smb_FreeTran2Packet(outp);
return CM_ERROR_BADSMB;
}
-
+
userp = smb_GetTran2User(vcp, p);
if (!userp) {
osi_Log1(smb_logp, "T2SDSingle search dir unable to resolve user [%d]", p->uid);
/* 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);
if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
- code = CM_ERROR_BADSHARENAME;
+ code = CM_ERROR_NOSUCHPATH;
smb_SendTran2Error(vcp, p, opx, code);
smb_FreeTran2Packet(outp);
return 0;
#endif /* DFS_SUPPORT */
osi_Log1(smb_logp,"T2SDSingle scp 0x%p", scp);
- /* now do a single case sensitive lookup for the file in question */
- code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE, userp, &req, &targetscp);
+ afs_ioctl = (cm_ClientStrCmpI(maskp, CM_IOCTL_FILENAME_NOSLASH_W) == 0);
- /* if a case sensitive match failed, we try a case insensitive one
- next. */
- if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) {
- code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE | CM_FLAG_CASEFOLD, userp, &req, &targetscp);
- }
+ /*
+ * If we are not searching for _._AFS_IOCTL_._, then we need to obtain
+ * the target scp.
+ */
+ if (!afs_ioctl) {
+ /* now do a single case sensitive lookup for the file in question */
+ code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE, userp, &req, &targetScp);
- if (code == 0 && targetscp->fid.vnode == 0) {
- cm_ReleaseSCache(targetscp);
- code = CM_ERROR_NOSUCHFILE;
- }
+ /*
+ * if a case sensitive match failed, we try a case insensitive
+ * one next.
+ */
+ if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH)
+ code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE | CM_FLAG_CASEFOLD, userp, &req, &targetScp);
- if (code) {
- /* if we can't find the directory entry, this block will
- return CM_ERROR_NOSUCHFILE, which we will pass on to
- smb_ReceiveTran2SearchDir(). */
- cm_ReleaseSCache(scp);
- cm_ReleaseUser(userp);
- if (code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) {
- smb_SendTran2Error(vcp, p, opx, code);
- code = 0;
- }
- smb_FreeTran2Packet(outp);
- return code;
+ if (code == 0 && targetScp->fid.vnode == 0) {
+ cm_ReleaseSCache(targetScp);
+ code = CM_ERROR_NOSUCHFILE;
+ }
+
+ if (code) {
+ /*
+ * if we can't find the directory entry, this block will
+ * return CM_ERROR_NOSUCHFILE, which we will pass on to
+ * smb_ReceiveTran2SearchDir().
+ */
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ if (code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) {
+ smb_SendTran2Error(vcp, p, opx, code);
+ code = 0;
+ }
+ smb_FreeTran2Packet(outp);
+ return code;
+ }
}
/* now that we have the target in sight, we proceed with filling
fp = (smb_tran2Find_t *) op;
if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO
- && targetscp->fid.vnode != 0
&& !cm_Is8Dot3(maskp)) {
- cm_dirFid_t dfid;
- dfid.vnode = htonl(targetscp->fid.vnode);
- dfid.unique = htonl(targetscp->fid.unique);
+ /*
+ * Since the _._AFS_IOCTL_._ file does not actually exist
+ * we will make up a per directory FID equivalent to the
+ * directory vnode and the uniqifier 0.
+ */
+ if (afs_ioctl) {
+ dfid.vnode = htonl(scp->fid.vnode);
+ dfid.unique = htonl(0);
+ } else {
+ dfid.vnode = htonl(targetScp->fid.vnode);
+ dfid.unique = htonl(targetScp->fid.unique);
+ }
cm_Gen8Dot3NameIntW(maskp, &dfid, shortName, &shortNameEnd);
NeedShortName = 1;
}
osi_Log4(smb_logp, "T2SDSingle dir vn %u uniq %u name %S (%S)",
- htonl(targetscp->fid.vnode),
- htonl(targetscp->fid.unique),
+ ntohl(dfid.vnode),
+ ntohl(dfid.unique),
osi_LogSaveClientString(smb_logp, pathp),
(NeedShortName)? osi_LogSaveClientString(smb_logp, shortName) : _C(""));
}
if (!(attribute & SMB_ATTR_DIRECTORY) &&
- (targetscp->fileType == CM_SCACHETYPE_DIRECTORY ||
- targetscp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
- targetscp->fileType == CM_SCACHETYPE_DFSLINK ||
- targetscp->fileType == CM_SCACHETYPE_INVALID)) {
+ !afs_ioctl &&
+ (targetScp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ targetScp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ targetScp->fileType == CM_SCACHETYPE_DFSLINK ||
+ targetScp->fileType == CM_SCACHETYPE_INVALID)) {
code = CM_ERROR_NOSUCHFILE;
osi_Log0(smb_logp, "T2SDSingle skipping directory or bad link");
curPatchp->flags = 0;
}
- cm_SetFid(&curPatchp->fid, targetscp->fid.cell, targetscp->fid.volume, targetscp->fid.vnode, targetscp->fid.unique);
-
/* temp */
{
int namelen = cm_ClientStringToFsString(maskp, -1, NULL, 0);
dep = (cm_dirEntry_t *)malloc(sizeof(cm_dirEntry_t)+namelen);
cm_ClientStringToFsString(maskp, -1, dep->name, namelen);
}
- dep->fid.vnode = targetscp->fid.vnode;
- dep->fid.unique = targetscp->fid.unique;
+
+ if (afs_ioctl) {
+ cm_SetFid(&curPatchp->fid, scp->fid.cell, scp->fid.volume, scp->fid.vnode, 0);
+ dep->fid.vnode = scp->fid.vnode;
+ dep->fid.unique = 0;
+ curPatchp->flags |= SMB_DIRLISTPATCH_IOCTL;
+ } else {
+ cm_SetFid(&curPatchp->fid, targetScp->fid.cell, targetScp->fid.volume, targetScp->fid.vnode, targetScp->fid.unique);
+ dep->fid.vnode = targetScp->fid.vnode;
+ dep->fid.unique = targetScp->fid.unique;
+ }
+
curPatchp->dep = dep;
- }
+ }
if (searchFlags & TRAN2_FIND_FLAG_RETURN_RESUME_KEYS) {
/* put out resume key */
if (dep)
free(dep);
if (scp)
- cm_ReleaseSCache(scp);
- cm_ReleaseSCache(targetscp);
+ cm_ReleaseSCache(scp);
+ if (targetScp)
+ cm_ReleaseSCache(targetScp);
cm_ReleaseUser(userp);
return code;
pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[6]), NULL, SMB_STRF_ANSIPATH);
nextCookie = 0;
maskp = cm_ClientStrRChr(pathp, '\\');
- if (maskp == NULL)
+ if (maskp == NULL)
maskp = pathp;
- else
+ else
maskp++; /* skip over backslash */
/* track if this is likely to match a lot of entries */
#ifndef NOFINDFIRSTOPTIMIZE
if (!starPattern) {
/* if this is for a single directory or file, we let the
- optimized routine handle it. The only error it
+ optimized routine handle it. The only error it
returns is CM_ERROR_NOSUCHFILE. The */
code = smb_T2SearchDirSingle(vcp, p, opx);
maxReturnData = p->maxReturnData;
if (p->opcode == 1) /* find first */
maxReturnParms = 10; /* bytes */
- else
+ else
maxReturnParms = 8; /* bytes */
outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
osi_Log2(smb_logp, "T2 receive search dir count %d [%S]",
maxCount, osi_LogSaveClientString(smb_logp, pathp));
-
+
/* bail out if request looks bad */
if (p->opcode == 1 && !pathp) {
smb_ReleaseDirSearch(dsp);
smb_FreeTran2Packet(outp);
return CM_ERROR_BADSMB;
}
-
+
osi_Log3(smb_logp, "T2 search dir id %d, nextCookie 0x%x, attr 0x%x",
dsp->cookie, nextCookie, attribute);
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);
if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
- code = CM_ERROR_BADSHARENAME;
+ code = CM_ERROR_NOSUCHPATH;
smb_SendTran2Error(vcp, p, opx, code);
smb_FreeTran2Packet(outp);
lock_ReleaseMutex(&dsp->mx);
*/
cm_HoldSCache(scp);
dsp->flags |= SMB_DIRSEARCH_BULKST;
- }
+ }
}
lock_ReleaseMutex(&dsp->mx);
if (code) {
/* we're in a later dir page */
if (temp < 32) temp = 32;
}
-
+
/* make sure the low order 5 bits are zero */
temp &= ~(32-1);
-
+
/* now put temp bits back ito curOffset.LowPart */
curOffset.LowPart &= ~(2048-1);
curOffset.LowPart |= temp;
break;
}
- /* when we have obtained as many entries as can be processed in
+ /* when we have obtained as many entries as can be processed in
* a single Bulk Status call to the file server, apply the dir listing
* patches.
*/
if (bufferp) {
buf_Release(bufferp);
bufferp = NULL;
- }
+ }
lock_ReleaseWrite(&scp->rw);
- code = buf_Get(scp, &thyper, &bufferp);
+ code = buf_Get(scp, &thyper, &req, &bufferp);
lock_ObtainWrite(&scp->rw);
if (code) {
osi_Log2(smb_logp, "T2 search dir buf_Get scp %x failed %d", scp, code);
osi_Log2(smb_logp, "T2 search dir cm_SyncOp scp %x failed %d", scp, code);
break;
}
-
+
if (cm_HaveBuffer(scp, bufferp, 0)) {
osi_Log2(smb_logp, "T2 search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
&req);
cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
if (code) {
- osi_Log3(smb_logp, "T2 search dir cm_GetBuffer failed scp %x bufferp %x code %d",
+ osi_Log3(smb_logp, "T2 search dir cm_GetBuffer failed scp %x bufferp %x code %d",
scp, bufferp, code);
break;
}
break;
}
} /* if (wrong buffer) ... */
-
+
/* now we have the buffer containing the entry we're interested
* in; copy it out if it represents a non-deleted entry.
*/
* XXXX Probably should do more sanity checking.
*/
numDirChunks = cm_NameEntries(dep->name, &onbytes);
-
+
/* compute offset of cookie representing next entry */
nextEntryCookie = curOffset.LowPart + (CM_DIR_CHUNKSIZE * numDirChunks);
- if (dep->fid.vnode == 0)
+ if (dep->fid.vnode == 0)
goto nextEntry; /* This entry is not in use */
if (cm_FsStringToClientString(dep->name, -1, cfileName, lengthof(cfileName)) == 0 ||
/* Need 8.3 name? */
NeedShortName = 0;
- if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO &&
+ if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO &&
!cm_Is8Dot3(cfileName)) {
cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
NeedShortName = 1;
}
osi_Log4(smb_logp, "T2 search dir vn %u uniq %u name %S (%S)",
- dep->fid.vnode, dep->fid.unique,
+ dep->fid.vnode, dep->fid.unique,
osi_LogSaveClientString(smb_logp, cfileName),
NeedShortName ? osi_LogSaveClientString(smb_logp, shortName) : _C(""));
/* 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.
+ * If we get a non-wildcard match, it's a lookup for a specific file.
*/
if (cm_MatchMask(normName, maskp, (starPattern? CM_FLAG_CASEFOLD : 0)) ||
- (NeedShortName && cm_MatchMask(shortName, maskp, CM_FLAG_CASEFOLD)))
+ (NeedShortName && cm_MatchMask(shortName, maskp, CM_FLAG_CASEFOLD)))
{
/* Eliminate entries that don't match requested attributes */
- if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) &&
+ if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) &&
smb_IsDotFile(cfileName)) {
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 */
if (orbytes + bytesInBuffer + align > maxReturnData) {
osi_Log1(smb_logp, "T2 dir search exceed max return data %d",
maxReturnData);
- break;
- }
+ break;
+ }
/* this is one of the entries to use: it is not deleted
* and it matches the star pattern we're looking for.
/* temp */
curPatchp->dep = dep;
- }
+ }
if (searchFlags & TRAN2_FIND_FLAG_RETURN_RESUME_KEYS)
/* put out resume key */
curOffset = LargeIntegerAdd(thyper, curOffset);
} /* while copying data for dir listing */
- /* If we didn't get a star pattern, we did an exact match during the first pass.
+ /* If we didn't get a star pattern, we did an exact match during the first pass.
* If there were no exact matches found, we fail over to inexact matches by
* marking the query as a star pattern (matches all case permutations), and
- * re-running the query.
+ * re-running the query.
*/
if (returnedNames == 0 && !starPattern && foundInexact) {
osi_Log0(smb_logp,"T2 Search: No exact matches. Re-running for inexact matches");
bufferp = NULL;
}
- /*
+ /*
* Finally, process whatever entries we have left.
*/
code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath,
dsp->relPath, infoLevel, userp, &req);
/* now put out the final parameters */
- if (returnedNames == 0)
+ if (returnedNames == 0)
eos = 1;
if (p->opcode == 1) {
/* find first */
outp->parmsp[1] = returnedNames;
outp->parmsp[2] = eos;
outp->parmsp[3] = 0; /* nothing wrong with EAS */
- outp->parmsp[4] = 0;
+ outp->parmsp[4] = 0;
/* don't need last name to continue
* search, cookie is enough. Normally,
* this is the offset of the file name
outp->parmsp[2] = 0; /* EAS error */
outp->parmsp[3] = 0; /* last name, as above */
outp->totalParms = 8; /* in bytes */
- }
+ }
/* return # of bytes in the buffer */
outp->totalData = bytesInBuffer;
* we're supposed to close the search if we're done, and we're done,
* or if something went wrong, close the search.
*/
- if ((searchFlags & TRAN2_FIND_FLAG_CLOSE_SEARCH) ||
+ if ((searchFlags & TRAN2_FIND_FLAG_CLOSE_SEARCH) ||
(returnedNames == 0) ||
- ((searchFlags & TRAN2_FIND_FLAG_CLOSE_SEARCH_IF_END) && eos) ||
+ ((searchFlags & TRAN2_FIND_FLAG_CLOSE_SEARCH_IF_END) && eos) ||
code != 0)
smb_DeleteDirSearch(dsp);
smb_dirSearch_t *dsp;
dirHandle = smb_GetSMBParm(inp, 0);
-
+
osi_Log1(smb_logp, "SMB3 find close handle %d", dirHandle);
dsp = smb_FindDirSearch(dirHandle);
-
+
if (!dsp)
return CM_ERROR_BADFD;
-
+
/* otherwise, we have an FD to destroy */
smb_DeleteDirSearch(dsp);
smb_ReleaseDirSearch(dsp);
-
+
/* and return results */
smb_SetSMBDataLength(outp, 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;
clientchar_t *tidPathp;
cm_req_t req;
int created = 0;
+ BOOL is_rpc = FALSE;
+ BOOL is_ipc = FALSE;
smb_InitReq(&req);
scp = NULL;
-
+
extraInfo = (smb_GetSMBParm(inp, 2) & 1); /* return extra info */
openFun = smb_GetSMBParm(inp, 8); /* open function */
excl = ((openFun & 3) == 0);
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)
+ return CM_ERROR_BADSMB;
+
+ code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+ if (code) {
+ if (code == CM_ERROR_TIDIPC) {
+ is_ipc = TRUE;
+ } else {
+ return CM_ERROR_NOSUCHPATH;
+ }
+ }
spacep = inp->spacep;
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
- if (lastNamep &&
- (cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0)) {
+ if (lastNamep &&
+
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
-#ifdef NOTSERVICE
- osi_Log0(smb_logp, "IOCTL Open");
-#endif
+ (cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
+
+ /* Or an RPC endpoint (is_rpc = TRUE assignment is intentional) */
+ (is_ipc && MSRPC_IsWellKnownService(lastNamep) && (is_rpc = TRUE)))) {
+
+ unsigned short file_type = 0;
+ unsigned short device_state = 0;
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- smb_SetupIoctlFid(fidp, spacep);
+ if (is_rpc) {
+ code = smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+ osi_Log1(smb_logp, "OpenAndX Setting up RPC on fid[%d]", fidp->fid);
+ if (code) {
+ osi_Log1(smb_logp, "smb_SetupRPCFid failure code [%d]", code);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+ } else {
+ smb_SetupIoctlFid(fidp, spacep);
+ osi_Log1(smb_logp, "OpenAndX Setting up IOCTL on fid[%d]", fidp->fid);
+ }
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fidp->fid;
-
+
/* copy out remainder of the parms */
parmSlot = 2;
smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* len */
smb_SetSMBParm(outp, parmSlot, 0x7fff); parmSlot++;
smb_SetSMBParm(outp, parmSlot, openMode); parmSlot++;
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* file type 0 ==> normal file or dir */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* IPC junk */
- }
+ smb_SetSMBParm(outp, parmSlot, file_type); parmSlot++;
+ smb_SetSMBParm(outp, parmSlot, device_state); parmSlot++;
+ }
/* and the final "always present" stuff */
smb_SetSMBParm(outp, parmSlot, /* openAction found existing file */ 1); parmSlot++;
/* next write out the "unique" ID */
return 0;
}
- if (!cm_IsValidClientString(pathp)) {
-#ifdef DEBUG
- clientchar_t * hexp;
+#ifndef DFS_SUPPORT
+ if (is_ipc) {
+ osi_Log0(smb_logp, "NTOpenX rejecting IPC TID");
+ return CM_ERROR_BADFD;
+ }
+#endif
+
+ if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
hexp = cm_GetRawCharsAlloc(pathp, -1);
osi_Log1(smb_logp, "NTOpenX rejecting invalid name. [%S]",
userp = smb_GetUserFromVCP(vcp, inp);
dscp = NULL;
- code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
- if (code) {
- cm_ReleaseUser(userp);
- return CM_ERROR_NOSUCHPATH;
- }
- 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 ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#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;
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#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.
*/
- if (!lastNamep)
+ if (!lastNamep)
lastNamep = pathp;
- else
+ else
lastNamep++;
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
&req, &scp);
return code;
}
}
-
+
/* if we get here, if code is 0, the file exists and is represented by
* scp. Otherwise, we have to create it. The dir may be represented
* by dscp, or we may have found the file directly. If code is non-zero,
if (excl) {
/* oops, file shouldn't be there */
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
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) {
setAttr.length.LowPart = 0;
setAttr.length.HighPart = 0;
code = cm_SetAttr(scp, &setAttr, userp, &req);
- }
+ }
} /* lookup succeeded */
}
}
-
+
/* we don't need this any longer */
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
if (code) {
/* something went wrong creating or truncating the file */
- if (scp)
+ if (scp)
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
return code;
}
-
+
/* make sure we're about to open a file */
if (scp->fileType != CM_SCACHETYPE_FILE) {
cm_ReleaseSCache(scp);
/* now all we have to do is open the file itself */
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
osi_assertx(fidp, "null smb_fid_t");
-
+
cm_HoldUser(userp);
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
osi_Log2(smb_logp,"smb_ReceiveV3OpenX fidp 0x%p scp 0x%p", fidp, scp);
/* also the user */
fidp->userp = userp;
-
+
/* compute open mode */
- if (openMode != 1)
+ if (openMode != 1)
fidp->flags |= SMB_FID_OPENREAD_LISTDIR;
if (openMode == 1 || openMode == 2)
fidp->flags |= SMB_FID_OPENWRITE;
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
-
+
cm_Open(scp, 0, userp);
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fidp->fid;
-
+
/* copy out remainder of the parms */
parmSlot = 2;
smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
cm_ReleaseUser(userp);
/* leave scp held since we put it in fidp->scp */
return 0;
-}
+}
-static void smb_GetLockParams(unsigned char LockType,
- char ** buf,
- unsigned int * ppid,
- LARGE_INTEGER * pOffset,
+static void smb_GetLockParams(unsigned char LockType,
+ char ** buf,
+ unsigned int * ppid,
+ LARGE_INTEGER * pOffset,
LARGE_INTEGER * pLength)
{
if (LockType & LOCKING_ANDX_LARGE_FILES) {
int i;
cm_key_t key;
unsigned int pid;
+ afs_uint32 smb_vc_hold_required = 0;
smb_InitReq(&req);
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);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
- lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL) {
osi_Log0(smb_logp, "smb_ReceiveV3Locking BadFD");
lock_ReleaseMutex(&fidp->mx);
inp->fid = fid;
userp = smb_GetUserFromVCP(vcp, inp);
-
+ smb_HoldVC(vcp);
lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
if (LockType & LOCKING_ANDX_CHANGE_LOCKTYPE) {
/* AFS does not support atomic changes of lock types from read or write and vice-versa */
- osi_Log0(smb_logp, "smb_ReceiveV3Locking received unsupported request [LOCKING_ANDX_CHANGE_LOCKTYPE]");
+ osi_Log0(smb_logp, "smb_ReceiveV3Locking received unsupported request [LOCKING_ANDX_CHANGE_LOCKTYPE]");
code = CM_ERROR_BADOP;
goto done;
for (wlRequest = smb_allWaitingLocks; wlRequest; wlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q))
{
for (wl = wlRequest->locks; wl; wl = (smb_waitingLock_t *) osi_QNext(&wl->q)) {
- if (cm_KeyEquals(&wl->key, &key, 0) && LargeIntegerEqualTo(wl->LOffset, LOffset) &&
+ if (cm_KeyEquals(&wl->key, &key, 0) && LargeIntegerEqualTo(wl->LOffset, LOffset) &&
LargeIntegerEqualTo(wl->LLength, LLength)) {
wl->state = SMB_WAITINGLOCKSTATE_CANCELLED;
goto found_lock_request;
key = cm_GenerateKey(vcp->vcID, pid, fidp->fid);
- code = cm_Unlock(scp, LockType, LOffset, LLength, key, userp, &req);
+ code = cm_Unlock(scp, LockType, LOffset, LLength, key, 0, userp, &req);
- if (code)
+ if (code)
goto done;
}
code = cm_Lock(scp, LockType, LOffset, LLength, key, (Timeout != 0),
userp, &req, &lockp);
- if (code == CM_ERROR_NOACCESS && LockType == LockWrite &&
+ if (code == CM_ERROR_NOACCESS && LockType == LockWrite &&
(fidp->flags & (SMB_FID_OPENREAD_LISTDIR | SMB_FID_OPENWRITE)) == SMB_FID_OPENREAD_LISTDIR)
{
code = cm_Lock(scp, LockRead, LOffset, LLength, key, (Timeout != 0),
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 */
osi_assertx(wlRequest != NULL, "null wlRequest");
wlRequest->vcp = vcp;
- smb_HoldVC(vcp);
+ smb_vc_hold_required = 1;
wlRequest->scp = scp;
osi_Log2(smb_logp,"smb_ReceiveV3LockingX wlRequest 0x%p scp 0x%p", wlRequest, scp);
cm_HoldSCache(scp);
wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
- ul_code = cm_Unlock(scp, LockType, wl->LOffset, wl->LLength, wl->key, userp, &req);
-
+ ul_code = cm_Unlock(scp, LockType, wl->LOffset, wl->LLength, wl->key, 0, userp, &req);
+
if(ul_code != 0) {
osi_Log1(smb_logp, "smb_ReceiveV3Locking cm_Unlock returns code %d", ul_code);
} else {
smb_SetSMBDataLength(outp, 0);
}
- done:
+ done:
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
doneSync:
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
+ if (!smb_vc_hold_required)
+ smb_HoldVC(vcp);
return code;
}
fid = smb_GetSMBParm(inp, 0);
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);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
- lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL) {
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
osi_Log2(smb_logp,"smb_ReceiveV3GetAttributes fidp 0x%p scp 0x%p", fidp, scp);
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
-
+
userp = smb_GetUserFromVCP(vcp, inp);
-
-
+
+
/* otherwise, stat the file */
lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code)
+ if (code)
goto done;
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
* call provides the date first, not the time, as returned in the
* searchTime variable. So we take the high-order bits first.
*/
- smb_SearchTimeFromUnixTime(&searchTime, scp->clientModTime);
+ cm_SearchTimeFromUnixTime(&searchTime, scp->clientModTime);
smb_SetSMBParm(outp, 0, (searchTime >> 16) & 0xffff); /* ctime */
smb_SetSMBParm(outp, 1, searchTime & 0xffff);
smb_SetSMBParm(outp, 2, (searchTime >> 16) & 0xffff); /* atime */
/* file attribute */
smb_SetSMBParm(outp, 10, smb_Attributes(scp));
-
+
/* and finalize stuff */
smb_SetSMBDataLength(outp, 0);
code = 0;
done:
- if (readlock)
+ if (readlock)
lock_ReleaseRead(&scp->rw);
else
lock_ReleaseWrite(&scp->rw);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
return code;
-}
+}
/* SMB_COM_SET_INFORMATION2 */
long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
fid = smb_GetSMBParm(inp, 0);
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);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
- lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL) {
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
osi_Log2(smb_logp,"smb_ReceiveV3SetAttributes fidp 0x%p scp 0x%p", fidp, scp);
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
-
+
userp = smb_GetUserFromVCP(vcp, inp);
-
-
+
/* now prepare to call cm_setattr. This message only sets various times,
* and AFS only implements mtime, and we'll set the mtime if that's
* requested. The others we'll ignore.
*/
searchTime = smb_GetSMBParm(inp, 5) | (smb_GetSMBParm(inp, 6) << 16);
-
+
if (searchTime != 0) {
- smb_UnixTimeFromSearchTime(&unixTime, searchTime);
+ cm_UnixTimeFromSearchTime(&unixTime, searchTime);
if ( unixTime != -1 ) {
attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
osi_Log1(smb_logp, "SMB receive V3SetAttributes [fid=%ld]", fid);
} else {
- osi_Log1(smb_logp, "**smb_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
+ osi_Log1(smb_logp, "**cm_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
}
}
- else
+ else
code = 0;
cm_ReleaseSCache(scp);
smb_fid_t *fidp;
smb_t *smbp = (smb_t*) inp;
long code = 0;
+ cm_scache_t *scp;
cm_user_t *userp;
char *op;
int inDataBlockCount;
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);
osi_Log4(smb_logp, "smb_ReceiveV3WriteX fid %d, off 0x%x:%08x, size 0x%x",
fd, offset.HighPart, offset.LowPart, count);
-
+
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);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
- lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL) {
lock_ReleaseMutex(&fidp->mx);
code = smb_IoctlV3Write(fidp, vcp, inp, outp);
smb_ReleaseFID(fidp);
return code;
}
+
+ if (fidp->flags & SMB_FID_RPC) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = smb_RPCV3Write(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+
+ if (!fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_BADFDOP;
+ }
+
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
+
userp = smb_GetUserFromVCP(vcp, inp);
/* special case: 0 bytes transferred means there is no data
cm_key_t key;
LARGE_INTEGER LOffset;
LARGE_INTEGER LLength;
- cm_scache_t * scp;
pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
LLength.HighPart = 0;
LLength.LowPart = count;
- scp = fidp->scp;
lock_ObtainWrite(&scp->rw);
code = cm_LockCheckWrite(scp, LOffset, LLength, key);
lock_ReleaseWrite(&scp->rw);
*/
lock_ObtainMutex(&fidp->mx);
if ((fidp->flags & SMB_FID_MTIMESETDONE) != SMB_FID_MTIMESETDONE) {
- fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
- fidp->scp->clientModTime = time(NULL);
+ lock_ObtainWrite(&fidp->scp->rw);
+ scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
+ scp->clientModTime = time(NULL);
+ lock_ReleaseWrite(&fidp->scp->rw);
}
lock_ReleaseMutex(&fidp->mx);
smb_SetSMBDataLength(outp, 0);
done:
+
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
smb_fid_t *fidp;
smb_t *smbp = (smb_t*) inp;
long code = 0;
+ cm_scache_t *scp;
cm_user_t *userp;
cm_key_t key;
char *op;
-
- fd = smb_GetSMBParm(inp, 2);
- count = smb_GetSMBParm(inp, 5);
+
+ fd = smb_GetSMBParm(inp, 2); /* File ID */
+ count = smb_GetSMBParm(inp, 5); /* MaxCount */
offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
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;
}
+ lock_ObtainMutex(&fidp->mx);
+
+ if (fidp->flags & SMB_FID_IOCTL) {
+ lock_ReleaseMutex(&fidp->mx);
+ inp->fid = fd;
+ code = smb_IoctlV3Read(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+
+ if (fidp->flags & SMB_FID_RPC) {
+ lock_ReleaseMutex(&fidp->mx);
+ inp->fid = fd;
+ code = smb_RPCV3Read(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+
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;
}
+ if (!fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_BADFDOP;
+ }
+
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
+
+ lock_ReleaseMutex(&fidp->mx);
+
pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
{
LARGE_INTEGER LOffset, LLength;
- cm_scache_t *scp;
LOffset.HighPart = offset.HighPart;
LOffset.LowPart = offset.LowPart;
LLength.HighPart = 0;
LLength.LowPart = count;
- scp = fidp->scp;
lock_ObtainWrite(&scp->rw);
code = cm_LockCheckRead(scp, LOffset, LLength, key);
lock_ReleaseWrite(&scp->rw);
}
+ cm_ReleaseSCache(scp);
if (code) {
smb_ReleaseFID(fidp);
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fd;
- lock_ObtainMutex(&fidp->mx);
- if (fidp->flags & SMB_FID_IOCTL) {
- lock_ReleaseMutex(&fidp->mx);
- code = smb_IoctlV3Read(fidp, vcp, inp, outp);
- smb_ReleaseFID(fidp);
- return code;
- }
- lock_ReleaseMutex(&fidp->mx);
-
userp = smb_GetUserFromVCP(vcp, inp);
/* 0 and 1 are reserved for request chaining, were setup by our caller,
* know where the data really is.
*/
op = smb_GetSMBData(outp, NULL);
-
+
/* now fill in offset from start of SMB header to first data byte (to op) */
smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
return code;
-}
-
+}
+
/*
* Values for createDisp, copied from NTDDK.H
*/
unsigned int createDisp;
unsigned int createOptions;
unsigned int shareAccess;
- int initialModeBits;
unsigned short baseFid;
smb_fid_t *baseFidp;
smb_fid_t *fidp;
int prefetch = 0;
int checkDoneRequired = 0;
cm_lock_data_t *ldp = NULL;
+ BOOL is_rpc = FALSE;
+ BOOL is_ipc = FALSE;
smb_InitReq(&req);
/* This code is very long and has a lot of if-then-else clauses
- * scp and dscp get reused frequently and we need to ensure that
+ * scp and dscp get reused frequently and we need to ensure that
* we don't lose a reference. Start by ensuring that they are NULL.
*/
scp = NULL;
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));
osi_Log4(smb_logp,"... da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
osi_Log3(smb_logp,"... share=[%x] flags=[%x] lastNamep=[%S]", shareAccess, flags, osi_LogSaveClientString(smb_logp,(lastNamep?lastNamep:_C("null"))));
- if (lastNamep &&
- (cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0)) {
- /* special case magic file name for receiving IOCTL requests
- * (since IOCTL calls themselves aren't getting through).
- */
+ if (baseFid == 0) {
+ baseFidp = NULL;
+ 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
+ * 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, "NTCreateX received IPC TID");
+ is_ipc = TRUE;
+ }
+ }
+
+ osi_Log1(smb_logp, "NTCreateX tidPathp=[%S]", (tidPathp==NULL)?_C("null"): osi_LogSaveClientString(smb_logp,tidPathp));
+
+ if (lastNamep &&
+
+ ((is_ipc && MSRPC_IsWellKnownService(lastNamep) && (is_rpc = TRUE)) ||
+
+ /* special case magic file name for receiving IOCTL requests
+ * (since IOCTL calls themselves aren't getting through).
+ */
+ cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0)) {
+
+ unsigned short file_type = 0;
+ unsigned short device_state = 0;
+
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- smb_SetupIoctlFid(fidp, spacep);
- osi_Log1(smb_logp,"NTCreateX Setting up IOCTL on fid[%d]",fidp->fid);
+
+ if (is_rpc) {
+ code = smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+ osi_Log1(smb_logp, "NTCreateX Setting up RPC on fid[%d]", fidp->fid);
+ if (code) {
+ osi_Log1(smb_logp, "smb_SetupRPCFid() failure code [%d]", code);
+ smb_ReleaseFID(fidp);
+ free(realPathp);
+ return code;
+ }
+ } else {
+ smb_SetupIoctlFid(fidp, spacep);
+ osi_Log1(smb_logp, "NTCreateX Setting up IOCTL on fid[%d]", fidp->fid);
+ }
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fidp->fid;
sz.HighPart = 0x7fff; sz.LowPart = 0;
smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* alen */
smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* len */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* dev state */
+ smb_SetSMBParm(outp, parmSlot, file_type); parmSlot++; /* filetype */
+ smb_SetSMBParm(outp, parmSlot, device_state); parmSlot++; /* dev state */
smb_SetSMBParmByte(outp, parmSlot, 0); /* is a dir? */
smb_SetSMBDataLength(outp, 0);
return 0;
}
+#ifndef DFS_SUPPORT
+ if (is_ipc) {
+ osi_Log0(smb_logp, "NTCreateX rejecting IPC TID");
+ free(realPathp);
+ return CM_ERROR_BADFD;
+ }
+#endif
+
if (!cm_IsValidClientString(realPathp)) {
#ifdef DEBUG
clientchar_t * hexp;
osi_Log1(smb_logp, "NTCreateX rejecting invalid name. [%S]",
osi_LogSaveClientString(smb_logp, hexp));
if (hexp)
- free(hexp);
+ free(hexp);
#else
osi_Log0(smb_logp, "NTCreateX rejecting invalid name");
#endif
return CM_ERROR_INVAL;
}
- if (baseFid == 0) {
- baseFidp = NULL;
- 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 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 {
+ if (baseFidp != 0) {
baseFidp = smb_FindFID(vcp, baseFid, 0);
if (!baseFidp) {
osi_Log1(smb_logp, "NTCreateX Invalid base fid [%d]", baseFid);
+ cm_ReleaseUser(userp);
free(realPathp);
- cm_ReleaseUser(userp);
return CM_ERROR_INVAL;
- }
+ }
if (baseFidp->scp && (baseFidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
free(realPathp);
- cm_ReleaseUser(userp);
smb_CloseFID(vcp, baseFidp, NULL, 0);
smb_ReleaseFID(baseFidp);
+ cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
tidPathp = NULL;
}
- osi_Log1(smb_logp, "NTCreateX tidPathp=[%S]", (tidPathp==NULL)?_C("null"): osi_LogSaveClientString(smb_logp,tidPathp));
-
/* compute open mode */
fidflags = 0;
if (desiredAccess & DELETE)
code = 0;
/* For an exclusive create, we want to do a case sensitive match for the last component. */
- if ( createDisp == FILE_CREATE ||
+ if ( createDisp == FILE_CREATE ||
createDisp == FILE_OVERWRITE ||
createDisp == FILE_OVERWRITE_IF) {
code = cm_NameI(baseDirp, spacep->wdata, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
- if (baseFidp)
+ if (baseFidp)
smb_ReleaseFID(baseFidp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
userp, &req, &scp);
if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) {
- code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp,
+ code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp);
if (code == 0 && realDirFlag == 1) {
cm_ReleaseSCache(scp);
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);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
- if (baseFidp)
+ if (baseFidp)
smb_ReleaseFID(baseFidp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
/* 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;
-
+
if (!foundscp || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
/* look up parent directory */
/* If we are trying to create a path (i.e. multiple nested directories), then we don't *need*
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
- if (baseFidp)
+ if (baseFidp)
smb_ReleaseFID(baseFidp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#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)) {
if (*tp && !smb_IsLegalFilename(tp)) {
cm_ReleaseUser(userp);
- if (baseFidp)
+ if (baseFidp)
smb_ReleaseFID(baseFidp);
free(realPathp);
if (scp)
return CM_ERROR_EXISTS;
}
- if (!lastNamep)
+ if (!lastNamep)
lastNamep = realPathp;
- else
+ else
lastNamep++;
if (!smb_IsLegalFilename(lastNamep)) {
}
if (!foundscp && !treeCreate) {
- if ( createDisp == FILE_CREATE ||
+ if ( createDisp == FILE_CREATE ||
createDisp == FILE_OVERWRITE ||
- createDisp == FILE_OVERWRITE_IF)
+ createDisp == FILE_OVERWRITE_IF)
{
code = cm_Lookup(dscp, lastNamep,
CM_FLAG_FOLLOW, userp, &req, &scp);
return CM_ERROR_EXISTS;
}
- if ( createDisp == FILE_OVERWRITE ||
+ if ( createDisp == FILE_OVERWRITE ||
createDisp == FILE_OVERWRITE_IF) {
setAttr.mask = CM_ATTRMASK_LENGTH;
code = cm_SetAttr(scp, &setAttr, userp, &req);
openAction = 3; /* truncated existing file */
}
- else
+ else
openAction = 1; /* found existing file */
} else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
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;
int isLast = 0;
/* create directory */
- if ( !treeCreate )
+ if ( !treeCreate )
treeStartp = lastNamep;
osi_assertx(dscp != NULL, "null cm_scache_t");
osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%S]",
osi_LogSaveClientString(smb_logp, treeStartp));
openAction = 2; /* created directory */
- /* if the request is to create the root directory
+ /* if the request is to create the root directory
* it will appear as a directory name of the nul-string
* and a code of CM_ERROR_NOSUCHFILE
*/
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
+ smb_SetInitialModeBitsForDir(extAttributes, &setAttr);
pp = treeStartp;
cp = spacep->wdata;
}
pp = tp;
- if (clen == 0)
+ if (clen == 0)
continue; /* the supplied path can't have consecutive slashes either , but */
/* cp is the next component to be created. */
code = cm_Lookup(tscp1, cp, CM_FLAG_CASEFOLD,
userp, &req, &tscp2);
}
- if (code)
+ if (code)
break;
if (!isLast) { /* for anything other than dscp, release it unless it's the last one */
if (scp)
cm_ReleaseSCache(scp);
scp = tscp2;
- /*
+ /*
* if we get here and code == 0, then scp is the last directory created, and dscp is the
* parent of scp.
*/
/* something went wrong creating or truncating the file */
if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
- if (scp)
+ if (scp)
cm_ReleaseSCache(scp);
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
}
key = cm_GenerateKey(vcp->vcID, SMB_FID_QLOCK_PID, fidp->fid);
-
+
lock_ObtainWrite(&scp->rw);
code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
lock_ReleaseWrite(&scp->rw);
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;
- smb_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);
- if ((fidp->flags & SMB_FID_EXECUTABLE) &&
- LargeIntegerGreaterThanZero(fidp->scp->length) &&
+ /*
+ * 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) &&
!(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
prefetch = 1;
}
lock_ReleaseRead(&scp->rw);
if (prefetch)
- cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
- fidp->scp->length.LowPart, fidp->scp->length.HighPart,
+ cm_QueueBKGRequest(scp, cm_BkgPrefetch, 0, 0,
+ scp->length.LowPart, scp->length.HighPart,
userp);
/* leave scp held since we put it in fidp->scp */
return 0;
-}
+}
/*
* A lot of stuff copied verbatim from NT Create&X to NT Tran Create.
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
* is probably looking for DCE RPC end points which we
* don't support OR it could be looking to make a DFS
- * referral request.
+ * referral request.
*/
osi_Log0(smb_logp, "NTTranCreate received IPC TID");
#ifndef DFS_SUPPORT
free(realPathp);
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
-#endif
+#endif
}
} 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;
- }
+ }
if (baseFidp->scp && (baseFidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
free(realPathp);
dscp = NULL;
code = 0;
- if ( createDisp == FILE_OPEN ||
+ if ( createDisp == FILE_OPEN ||
createDisp == FILE_OVERWRITE ||
createDisp == FILE_OVERWRITE_IF) {
code = cm_NameI(baseDirp, spacep->wdata, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
userp, &req, &scp);
if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) {
- code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp,
+ code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp);
if (code == 0 && realDirFlag == 1) {
cm_ReleaseSCache(scp);
return CM_ERROR_EXISTS;
}
}
- } else
- dscp = NULL;
+ }
} else {
code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
}
- if (code == 0)
+ 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,
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
} else
code = 0;
-
+
cm_FreeSpace(spacep);
if (baseFidp)
if (!lastNamep)
lastNamep = realPathp;
- else
+ else
lastNamep++;
if (!smb_IsLegalFilename(lastNamep))
*/
if (code == 0) {
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
- if (code) {
+ if (code) {
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
}
else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
/* don't create if not found */
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
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) {
}
}
code = cm_SetAttr(scp, &setAttr, userp, &req);
- }
+ }
} /* lookup succeeded */
}
} else {
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,
*/
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
userp, &req, &scp);
- }
+ }
}
if (code) {
/* something went wrong creating or truncating the file */
if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
- if (scp)
+ if (scp)
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
}
key = cm_GenerateKey(vcp->vcID, SMB_FID_QLOCK_PID, fidp->fid);
-
+
lock_ObtainWrite(&scp->rw);
code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
lock_ReleaseWrite(&scp->rw);
lock_ReleaseMutex(&fidp->mx);
/* we don't need this any longer */
- if (dscp)
+ if (dscp)
cm_ReleaseSCache(dscp);
cm_Open(scp, 0, userp);
*((USHORT *)outData) = fidp->fid; outData += 2; /* fid */
*((ULONG *)outData) = openAction; outData += 4;
*((ULONG *)outData) = 0; outData += 4; /* EA error offset */
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
*((FILETIME *)outData) = ft; outData += 8; /* creation time */
*((FILETIME *)outData) = ft; outData += 8; /* last access time */
*((FILETIME *)outData) = ft; outData += 8; /* last write time */
*((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);
parmOffset = 8*4 + 39;
parmOffset += 1; /* pad to 4 */
dataOffset = parmOffset + 104;
-
+
parmSlot = 1;
outp->oddByte = 1;
/* Total Parameter Count */
smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
smb_SetSMBDataLength(outp, 105);
-
+
lock_ObtainRead(&scp->rw);
outData = smb_GetSMBData(outp, NULL);
outData++; /* round to get to parmOffset */
*((USHORT *)outData) = fidp->fid; outData += 2; /* fid */
*((ULONG *)outData) = openAction; outData += 4;
*((ULONG *)outData) = 0; outData += 4; /* EA error offset */
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
*((FILETIME *)outData) = ft; outData += 8; /* creation time */
*((FILETIME *)outData) = ft; outData += 8; /* last access time */
*((FILETIME *)outData) = ft; outData += 8; /* last write time */
*((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 */
}
- if ((fidp->flags & SMB_FID_EXECUTABLE) &&
- LargeIntegerGreaterThanZero(fidp->scp->length) &&
+ if ((fidp->flags & SMB_FID_EXECUTABLE) &&
+ LargeIntegerGreaterThanZero(scp->length) &&
!(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
prefetch = 1;
}
lock_ReleaseRead(&scp->rw);
if (prefetch)
- cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
- fidp->scp->length.LowPart, fidp->scp->length.HighPart,
+ cm_QueueBKGRequest(scp, cm_BkgPrefetch, 0, 0,
+ scp->length.LowPart, scp->length.HighPart,
userp);
osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
smb_packet_t *outp)
{
smb_packet_t *savedPacketp;
- ULONG filter;
+ ULONG filter;
USHORT fid, watchtree;
smb_fid_t *fidp;
cm_scache_t *scp;
-
+
filter = smb_GetSMBParm(inp, 19) |
(smb_GetSMBParm(inp, 20) << 16);
fid = smb_GetSMBParm(inp, 21);
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;
}
+ 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;
}
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
/* Create a copy of the Directory Watch Packet to use when sending the
* notification if in the future a matching change is detected.
smb_Directory_Watches = savedPacketp;
lock_ReleaseMutex(&smb_Dir_Watch_Lock);
- scp = fidp->scp;
- osi_Log3(smb_logp,"smb_ReceiveNTTranNotifyChange fidp 0x%p scp 0x%p file \"%S\"",
+ osi_Log3(smb_logp,"smb_ReceiveNTTranNotifyChange fidp 0x%p scp 0x%p file \"%S\"",
fidp, scp, osi_LogSaveClientString(smb_logp, fidp->NTopen_wholepathp));
osi_Log3(smb_logp, "Request for NotifyChange filter 0x%x fid %d wtree %d",
filter, fid, watchtree);
else
scp->flags |= CM_SCACHEFLAG_WATCHED;
lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
smb_ReleaseFID(fidp);
outp->flags |= SMB_PACKETFLAG_NOSEND;
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
/* We can handle long names */
if (vcp->flags & SMB_VCFLAG_USENT)
((smb_t *)outp)->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
-
+
switch (function) {
case 1: /* NT_TRANSACT_CREATE */
return smb_ReceiveNTTranCreate(vcp, inp, outp);
osi_Log0(smb_logp, "SMB NT Transact Set Quota - not implemented");
break;
}
- return CM_ERROR_INVAL;
+ return CM_ERROR_BADOP;
}
/*
* If we don't know the file name (i.e. a callback break), filename is
* NULL, and we return a zero-length list.
*
- * At present there is not a single call to smb_NotifyChange that
- * has the isDirectParent parameter set to FALSE.
+ * At present there is not a single call to smb_NotifyChange that
+ * has the isDirectParent parameter set to FALSE.
*/
void smb_NotifyChange(DWORD action, DWORD notifyFilter,
cm_scache_t *dscp, clientchar_t *filename, clientchar_t *otherFilename,
lastWatch = watch;
watch = watch->nextp;
continue;
- }
+ }
if (fidp->scp != dscp ||
fidp->scp->flags & CM_SCACHEFLAG_DELETED ||
(filter & notifyFilter) == 0 ||
- (!isDirectParent && !wtree))
+ (!isDirectParent && !wtree))
{
osi_Log1(smb_logp," skipping fidp->scp[%x]", fidp->scp);
lastWatch = watch;
osi_Log0(smb_logp, " Notify Change Stream Size");
if (filter & FILE_NOTIFY_CHANGE_STREAM_WRITE)
osi_Log0(smb_logp, " Notify Change Stream Write");
-
+
/* A watch can only be notified once. Remove it from the list */
nextWatch = watch->nextp;
if (watch == smb_Directory_Watches)
*((DWORD *)outData) = otherNameLen*2;
outData += 4; /* File Name Length */
smb_UnparseString(watch, outData, otherFilename, NULL, 0);
- }
+ }
}
/*
watch = nextWatch;
}
lock_ReleaseMutex(&smb_Dir_Watch_Lock);
-}
+}
/* SMB_COM_NT_CANCEL */
long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
watchtree = smb_GetSMBParm(watch, 22) & 0xffff;
if (vcp != watch->vcp)
- osi_Log2(smb_logp, "smb_ReceiveNTCancel: vcp %x not equal to watch vcp %x",
+ osi_Log2(smb_logp, "smb_ReceiveNTCancel: vcp %x not equal to watch vcp %x",
vcp, watch->vcp);
fidp = smb_FindFID(vcp, fid, 0);
if (fidp) {
- osi_Log3(smb_logp, "Cancelling change notification for fid %d wtree %d file %S",
+ osi_Log3(smb_logp, "Cancelling change notification for fid %d wtree %d file %S",
fid, watchtree,
(fidp ? osi_LogSaveClientString(smb_logp, fidp->NTopen_wholepathp) :_C("")));
scp = fidp->scp;
osi_Log2(smb_logp,"smb_ReceiveNTCancel fidp 0x%p scp 0x%p", fidp, scp);
- lock_ObtainWrite(&scp->rw);
- if (watchtree)
- scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
- else
- scp->flags &= ~CM_SCACHEFLAG_WATCHED;
- lock_ReleaseWrite(&scp->rw);
+ if (scp) {
+ lock_ObtainWrite(&scp->rw);
+ if (watchtree)
+ scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
+ else
+ scp->flags &= ~CM_SCACHEFLAG_WATCHED;
+ lock_ReleaseWrite(&scp->rw);
+ }
smb_ReleaseFID(fidp);
} else {
osi_Log2(smb_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);
tp = smb_GetSMBData(inp, NULL);
oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, 0);
+ if (!oldPathp)
+ return CM_ERROR_BADSMB;
newPathp = smb_ParseASCIIBlock(inp, tp, &tp, 0);
+ if (!newPathp)
+ return CM_ERROR_BADSMB;
osi_Log3(smb_logp, "NTRename for [%S]->[%S] type [%s]",
osi_LogSaveClientString(smb_logp, oldPathp),
code = smb_Rename(vcp,inp,oldPathp,newPathp,attrs);
} else if (rename_type == RENAME_FLAG_HARD_LINK) { /* RENAME_FLAG_HARD_LINK */
code = smb_Link(vcp,inp,oldPathp,newPathp);
- } else
+ } else
code = CM_ERROR_BADOP;
return code;
}
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;
+}