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