#ifndef DJGPP
#include <windows.h>
+#include <ntstatus.h>
#define SECURITY_WIN32
#include <security.h>
#include <lmaccess.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
-
#include <osi.h>
#include "afsd.h"
+#include <WINNT\afsreg.h>
#include "smb.h"
* request */
cm_user_t *smb_GetTran2User(smb_vc_t *vcp, smb_tran2Packet_t *inp)
{
- smb_user_t *uidp;
+ smb_user_t *uidp;
cm_user_t *up = NULL;
uidp = smb_FindUID(vcp, inp->uid, 0);
if (!uidp) return NULL;
- lock_ObtainMutex(&uidp->mx);
+ lock_ObtainMutex(&uidp->mx);
if (uidp->unp) {
up = uidp->unp->userp;
cm_HoldUser(up);
}
- lock_ReleaseMutex(&uidp->mx);
+ lock_ReleaseMutex(&uidp->mx);
smb_ReleaseUID(uidp);
*/
unsigned long smb_ExtAttributes(cm_scache_t *scp)
{
- unsigned long attrs;
-
- if (scp->fileType == CM_SCACHETYPE_DIRECTORY
- || scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
- attrs = SMB_ATTR_DIRECTORY;
- else
- attrs = 0;
- /*
- * We used to mark a file RO if it was in an RO volume, but that
- * turns out to be impolitic in NT. See defect 10007.
- */
+ unsigned long attrs;
+
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_INVALID)
+ {
+ attrs = SMB_ATTR_DIRECTORY;
+#ifdef SPECIAL_FOLDERS
+ attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
+#endif /* SPECIAL_FOLDERS */
+ } else if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
+ } else
+ attrs = 0;
+ /*
+ * We used to mark a file RO if it was in an RO volume, but that
+ * 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 & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+ attrs |= SMB_ATTR_READONLY; /* Read-only */
+#else
+ if ((scp->unixModeBits & 0222) == 0)
+ attrs |= SMB_ATTR_READONLY; /* Read-only */
#endif
- if ((scp->unixModeBits & 0222) == 0)
- attrs |= SMB_ATTR_READONLY; /* Read-only */
- if (attrs == 0)
- attrs = SMB_ATTR_NORMAL; /* FILE_ATTRIBUTE_NORMAL */
+ if (attrs == 0)
+ attrs = SMB_ATTR_NORMAL; /* FILE_ATTRIBUTE_NORMAL */
- return attrs;
+ return attrs;
}
int smb_V3IsStarMask(char *maskp)
{
char tc;
- while (tc = *maskp++)
- if (tc == '?' || tc == '*')
+ while (tc = *maskp++)
+ if (tc == '?' || tc == '*' || tc == '<' || tc == '>')
return 1;
- return 0;
+ return 0;
}
unsigned char *smb_ParseString(unsigned char *inp, char **chainpp)
{
if (chainpp) {
- /* skip over null-terminated string */
- *chainpp = inp + strlen(inp) + 1;
+ /* skip over null-terminated string */
+ *chainpp = inp + strlen(inp) + 1;
}
return inp;
}
-/*DEBUG do not checkin*/
void OutputDebugF(char * format, ...) {
va_list args;
int len;
OutputDebugF("Hexdump length [%d]",len);
- for(i=0;i<len;i++) {
+ for (i=0;i<len;i++) {
if(!(i%16)) {
if(i) {
osi_Log0(smb_logp, osi_LogSaveString(smb_logp, buf));
osi_Log0(smb_logp, osi_LogSaveString(smb_logp, buf));
strcat(buf,"\n");
OutputDebugString(buf);
-}
+ }
}
-/**/
#define SMB_EXT_SEC_PACKAGE_NAME "Negotiate"
-void smb_NegotiateExtendedSecurity(void ** secBlob, int * secBlobLength){
+
+void smb_NegotiateExtendedSecurity(void ** secBlob, int * secBlobLength) {
SECURITY_STATUS status, istatus;
- CredHandle creds = {0,0};
- TimeStamp expiry;
- SecBufferDesc secOut;
- SecBuffer secTok;
- CtxtHandle ctx;
- ULONG flags;
+ CredHandle creds = {0,0};
+ TimeStamp expiry;
+ SecBufferDesc secOut;
+ SecBuffer secTok;
+ CtxtHandle ctx;
+ ULONG flags;
- *secBlob = NULL;
- *secBlobLength = 0;
+ *secBlob = NULL;
+ *secBlobLength = 0;
OutputDebugF("Negotiating Extended Security");
- status = AcquireCredentialsHandle(
- NULL,
- SMB_EXT_SEC_PACKAGE_NAME,
- SECPKG_CRED_INBOUND,
- NULL,
- NULL,
- NULL,
- NULL,
- &creds,
- &expiry);
-
- if (status != SEC_E_OK) {
- /* Really bad. We return an empty security blob */
- OutputDebugF("AcquireCredentialsHandle failed with %lX", status);
- goto nes_0;
- }
+ status = AcquireCredentialsHandle( NULL,
+ SMB_EXT_SEC_PACKAGE_NAME,
+ SECPKG_CRED_INBOUND,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &creds,
+ &expiry);
+
+ if (status != SEC_E_OK) {
+ /* Really bad. We return an empty security blob */
+ OutputDebugF("AcquireCredentialsHandle failed with %lX", status);
+ goto nes_0;
+ }
- secOut.cBuffers = 1;
- secOut.pBuffers = &secTok;
- secOut.ulVersion = SECBUFFER_VERSION;
-
- secTok.BufferType = SECBUFFER_TOKEN;
- secTok.cbBuffer = 0;
- secTok.pvBuffer = NULL;
-
- ctx.dwLower = ctx.dwUpper = 0;
-
- status = AcceptSecurityContext(
- &creds,
- NULL,
- NULL,
- ASC_REQ_CONNECTION | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY,
- SECURITY_NETWORK_DREP,
- &ctx,
- &secOut,
- &flags,
- &expiry
- );
-
- if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
- OutputDebugF("Completing token...");
- istatus = CompleteAuthToken(&ctx, &secOut);
+ secOut.cBuffers = 1;
+ secOut.pBuffers = &secTok;
+ secOut.ulVersion = SECBUFFER_VERSION;
+
+ secTok.BufferType = SECBUFFER_TOKEN;
+ secTok.cbBuffer = 0;
+ secTok.pvBuffer = NULL;
+
+ ctx.dwLower = ctx.dwUpper = 0;
+
+ status = AcceptSecurityContext( &creds,
+ NULL,
+ NULL,
+ ASC_REQ_CONNECTION | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY,
+ SECURITY_NETWORK_DREP,
+ &ctx,
+ &secOut,
+ &flags,
+ &expiry
+ );
+
+ if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
+ OutputDebugF("Completing token...");
+ istatus = CompleteAuthToken(&ctx, &secOut);
if ( istatus != SEC_E_OK )
OutputDebugF("Token completion failed: %x", istatus);
- }
+ }
- if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) {
- if (secTok.pvBuffer) {
- *secBlobLength = secTok.cbBuffer;
- *secBlob = malloc( secTok.cbBuffer );
- memcpy(*secBlob, secTok.pvBuffer, secTok.cbBuffer );
- }
- } else {
+ if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) {
+ if (secTok.pvBuffer) {
+ *secBlobLength = secTok.cbBuffer;
+ *secBlob = malloc( secTok.cbBuffer );
+ memcpy(*secBlob, secTok.pvBuffer, secTok.cbBuffer );
+ }
+ } else {
if ( status != SEC_E_OK )
OutputDebugF("AcceptSecurityContext status != CONTINUE %lX", status);
}
/* Discard partial security context */
DeleteSecurityContext(&ctx);
- if (secTok.pvBuffer) FreeContextBuffer( secTok.pvBuffer );
+ if (secTok.pvBuffer) FreeContextBuffer( secTok.pvBuffer );
- /* Discard credentials handle. We'll reacquire one when we get the session setup X */
- FreeCredentialsHandle(&creds);
+ /* Discard credentials handle. We'll reacquire one when we get the session setup X */
+ FreeCredentialsHandle(&creds);
nes_0:
- return;
+ return;
}
struct smb_ext_context {
- CredHandle creds;
- CtxtHandle ctx;
- int partialTokenLen;
- void * partialToken;
-};
+ CredHandle creds;
+ CtxtHandle ctx;
+ int partialTokenLen;
+ void * partialToken;
+};
long smb_AuthenticateUserExt(smb_vc_t * vcp, char * usern, char * secBlobIn, int secBlobInLength, char ** secBlobOut, int * secBlobOutLength) {
SECURITY_STATUS status, istatus;
- CredHandle creds;
- TimeStamp expiry;
- long code = 0;
- SecBufferDesc secBufIn;
- SecBuffer secTokIn;
- SecBufferDesc secBufOut;
- SecBuffer secTokOut;
- CtxtHandle ctx;
- struct smb_ext_context * secCtx = NULL;
- struct smb_ext_context * newSecCtx = NULL;
- void * assembledBlob = NULL;
- int assembledBlobLength = 0;
- ULONG flags;
-
- OutputDebugF("In smb_AuthenticateUserExt");
-
- *secBlobOut = NULL;
- *secBlobOutLength = 0;
-
- if (vcp->flags & SMB_VCFLAG_AUTH_IN_PROGRESS) {
- secCtx = vcp->secCtx;
- lock_ObtainMutex(&vcp->mx);
- vcp->flags &= ~SMB_VCFLAG_AUTH_IN_PROGRESS;
- vcp->secCtx = NULL;
- lock_ReleaseMutex(&vcp->mx);
- }
+ CredHandle creds;
+ TimeStamp expiry;
+ long code = 0;
+ SecBufferDesc secBufIn;
+ SecBuffer secTokIn;
+ SecBufferDesc secBufOut;
+ SecBuffer secTokOut;
+ CtxtHandle ctx;
+ struct smb_ext_context * secCtx = NULL;
+ struct smb_ext_context * newSecCtx = NULL;
+ void * assembledBlob = NULL;
+ int assembledBlobLength = 0;
+ ULONG flags;
+
+ OutputDebugF("In smb_AuthenticateUserExt");
+
+ *secBlobOut = NULL;
+ *secBlobOutLength = 0;
+
+ if (vcp->flags & SMB_VCFLAG_AUTH_IN_PROGRESS) {
+ secCtx = vcp->secCtx;
+ lock_ObtainMutex(&vcp->mx);
+ vcp->flags &= ~SMB_VCFLAG_AUTH_IN_PROGRESS;
+ vcp->secCtx = NULL;
+ lock_ReleaseMutex(&vcp->mx);
+ }
if (secBlobIn) {
OutputDebugF("Received incoming token:");
creds = secCtx->creds;
ctx = secCtx->ctx;
- if (secCtx->partialToken) {
- assembledBlobLength = secCtx->partialTokenLen + secBlobInLength;
- assembledBlob = malloc(assembledBlobLength);
+ if (secCtx->partialToken) {
+ assembledBlobLength = secCtx->partialTokenLen + secBlobInLength;
+ assembledBlob = malloc(assembledBlobLength);
memcpy(assembledBlob,secCtx->partialToken, secCtx->partialTokenLen);
- memcpy(((BYTE *)assembledBlob) + secCtx->partialTokenLen, secBlobIn, secBlobInLength);
- }
- } else {
- status = AcquireCredentialsHandle(
- NULL,
- SMB_EXT_SEC_PACKAGE_NAME,
- SECPKG_CRED_INBOUND,
- NULL,
- NULL,
- NULL,
- NULL,
- &creds,
- &expiry);
-
- if (status != SEC_E_OK) {
- OutputDebugF("Can't acquire Credentials handle [%lX]", status);
- code = CM_ERROR_BADPASSWORD; /* means "try again when I'm sober" */
- goto aue_0;
- }
-
- ctx.dwLower = 0;
- ctx.dwUpper = 0;
- }
+ memcpy(((BYTE *)assembledBlob) + secCtx->partialTokenLen, secBlobIn, secBlobInLength);
+ }
+ } else {
+ status = AcquireCredentialsHandle( NULL,
+ SMB_EXT_SEC_PACKAGE_NAME,
+ SECPKG_CRED_INBOUND,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &creds,
+ &expiry);
+
+ if (status != SEC_E_OK) {
+ OutputDebugF("Can't acquire Credentials handle [%lX]", status);
+ code = CM_ERROR_BADPASSWORD; /* means "try again when I'm sober" */
+ goto aue_0;
+ }
+
+ ctx.dwLower = 0;
+ ctx.dwUpper = 0;
+ }
secBufIn.cBuffers = 1;
- secBufIn.pBuffers = &secTokIn;
- secBufIn.ulVersion = SECBUFFER_VERSION;
-
- secTokIn.BufferType = SECBUFFER_TOKEN;
- if (assembledBlob) {
- secTokIn.cbBuffer = assembledBlobLength;
- secTokIn.pvBuffer = assembledBlob;
- } else {
- secTokIn.cbBuffer = secBlobInLength;
- secTokIn.pvBuffer = secBlobIn;
- }
+ secBufIn.pBuffers = &secTokIn;
+ secBufIn.ulVersion = SECBUFFER_VERSION;
+
+ secTokIn.BufferType = SECBUFFER_TOKEN;
+ if (assembledBlob) {
+ secTokIn.cbBuffer = assembledBlobLength;
+ secTokIn.pvBuffer = assembledBlob;
+ } else {
+ secTokIn.cbBuffer = secBlobInLength;
+ secTokIn.pvBuffer = secBlobIn;
+ }
- secBufOut.cBuffers = 1;
- secBufOut.pBuffers = &secTokOut;
- secBufOut.ulVersion = SECBUFFER_VERSION;
-
- secTokOut.BufferType = SECBUFFER_TOKEN;
- secTokOut.cbBuffer = 0;
- secTokOut.pvBuffer = NULL;
-
- status = AcceptSecurityContext(
- &creds,
- ((secCtx)?&ctx:NULL),
- &secBufIn,
- ASC_REQ_CONNECTION | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY,
- SECURITY_NETWORK_DREP,
- &ctx,
- &secBufOut,
- &flags,
- &expiry
- );
-
- if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
- OutputDebugF("Completing token...");
- istatus = CompleteAuthToken(&ctx, &secBufOut);
+ secBufOut.cBuffers = 1;
+ secBufOut.pBuffers = &secTokOut;
+ secBufOut.ulVersion = SECBUFFER_VERSION;
+
+ secTokOut.BufferType = SECBUFFER_TOKEN;
+ secTokOut.cbBuffer = 0;
+ secTokOut.pvBuffer = NULL;
+
+ status = AcceptSecurityContext( &creds,
+ ((secCtx)?&ctx:NULL),
+ &secBufIn,
+ ASC_REQ_CONNECTION | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY,
+ SECURITY_NETWORK_DREP,
+ &ctx,
+ &secBufOut,
+ &flags,
+ &expiry
+ );
+
+ if (status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) {
+ OutputDebugF("Completing token...");
+ istatus = CompleteAuthToken(&ctx, &secBufOut);
if ( istatus != SEC_E_OK )
OutputDebugF("Token completion failed: %lX", istatus);
- }
+ }
- if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) {
- OutputDebugF("Continue needed");
+ if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) {
+ OutputDebugF("Continue needed");
- newSecCtx = malloc(sizeof(*newSecCtx));
+ newSecCtx = malloc(sizeof(*newSecCtx));
- newSecCtx->creds = creds;
- newSecCtx->ctx = ctx;
- newSecCtx->partialToken = NULL;
- newSecCtx->partialTokenLen = 0;
+ newSecCtx->creds = creds;
+ newSecCtx->ctx = ctx;
+ newSecCtx->partialToken = NULL;
+ newSecCtx->partialTokenLen = 0;
- lock_ObtainMutex( &vcp->mx );
- vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS;
- vcp->secCtx = newSecCtx;
- lock_ReleaseMutex( &vcp->mx );
+ lock_ObtainMutex( &vcp->mx );
+ vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS;
+ vcp->secCtx = newSecCtx;
+ lock_ReleaseMutex( &vcp->mx );
- code = CM_ERROR_GSSCONTINUE;
- }
+ 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) &&
- secTokOut.pvBuffer) {
- OutputDebugF("Need to send token back to client");
+ if ((status == SEC_I_COMPLETE_NEEDED || status == SEC_E_OK ||
+ status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) &&
+ secTokOut.pvBuffer) {
+ OutputDebugF("Need to send token back to client");
- *secBlobOutLength = secTokOut.cbBuffer;
- *secBlobOut = malloc(secTokOut.cbBuffer);
- memcpy(*secBlobOut, secTokOut.pvBuffer, secTokOut.cbBuffer);
+ *secBlobOutLength = secTokOut.cbBuffer;
+ *secBlobOut = malloc(secTokOut.cbBuffer);
+ memcpy(*secBlobOut, secTokOut.pvBuffer, secTokOut.cbBuffer);
OutputDebugF("Outgoing token:");
OutputDebugHexDump(*secBlobOut,*secBlobOutLength);
- } else if (status == SEC_E_INCOMPLETE_MESSAGE) {
- OutputDebugF("Incomplete message");
+ } else if (status == SEC_E_INCOMPLETE_MESSAGE) {
+ OutputDebugF("Incomplete message");
- newSecCtx = malloc(sizeof(*newSecCtx));
+ newSecCtx = malloc(sizeof(*newSecCtx));
- newSecCtx->creds = creds;
- newSecCtx->ctx = ctx;
- newSecCtx->partialToken = malloc(secTokOut.cbBuffer);
- memcpy(newSecCtx->partialToken, secTokOut.pvBuffer, secTokOut.cbBuffer);
- newSecCtx->partialTokenLen = secTokOut.cbBuffer;
+ newSecCtx->creds = creds;
+ newSecCtx->ctx = ctx;
+ newSecCtx->partialToken = malloc(secTokOut.cbBuffer);
+ memcpy(newSecCtx->partialToken, secTokOut.pvBuffer, secTokOut.cbBuffer);
+ newSecCtx->partialTokenLen = secTokOut.cbBuffer;
- lock_ObtainMutex( &vcp->mx );
- vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS;
- vcp->secCtx = newSecCtx;
- lock_ReleaseMutex( &vcp->mx );
+ lock_ObtainMutex( &vcp->mx );
+ vcp->flags |= SMB_VCFLAG_AUTH_IN_PROGRESS;
+ vcp->secCtx = newSecCtx;
+ lock_ReleaseMutex( &vcp->mx );
- code = CM_ERROR_GSSCONTINUE;
- }
+ code = CM_ERROR_GSSCONTINUE;
+ }
- if (status == SEC_E_OK || status == SEC_I_COMPLETE_NEEDED) {
- /* woo hoo! */
- SecPkgContext_Names names;
+ if (status == SEC_E_OK || status == SEC_I_COMPLETE_NEEDED) {
+ /* woo hoo! */
+ SecPkgContext_Names names;
- OutputDebugF("Authentication completed");
+ OutputDebugF("Authentication completed");
OutputDebugF("Returned flags : [%lX]", flags);
- if (!QueryContextAttributes(&ctx, SECPKG_ATTR_NAMES, &names)) {
+ if (!QueryContextAttributes(&ctx, SECPKG_ATTR_NAMES, &names)) {
OutputDebugF("Received name [%s]", names.sUserName);
strcpy(usern, names.sUserName);
strlwr(usern); /* in tandem with smb_GetNormalizedUsername */
OutputDebugF("QueryContextAttributes Names failed [%x]", GetLastError());
code = CM_ERROR_BADPASSWORD;
}
- } else if (!code) {
+ } else if (!code) {
switch ( status ) {
case SEC_E_INVALID_TOKEN:
OutputDebugF("Returning bad password :: INVALID_TOKEN");
default:
OutputDebugF("Returning bad password :: Status == %lX", status);
}
- code = CM_ERROR_BADPASSWORD;
- }
+ code = CM_ERROR_BADPASSWORD;
+ }
- if (secCtx) {
- if (secCtx->partialToken) free(secCtx->partialToken);
- free(secCtx);
- }
+ if (secCtx) {
+ if (secCtx->partialToken) free(secCtx->partialToken);
+ free(secCtx);
+ }
- if (assembledBlob) {
- free(assembledBlob);
- }
+ if (assembledBlob) {
+ free(assembledBlob);
+ }
- if (secTokOut.pvBuffer)
- FreeContextBuffer(secTokOut.pvBuffer);
+ if (secTokOut.pvBuffer)
+ FreeContextBuffer(secTokOut.pvBuffer);
- if (code != CM_ERROR_GSSCONTINUE) {
- DeleteSecurityContext(&ctx);
- FreeCredentialsHandle(&creds);
- }
+ if (code != CM_ERROR_GSSCONTINUE) {
+ DeleteSecurityContext(&ctx);
+ FreeCredentialsHandle(&creds);
+ }
aue_0:
- return code;
+ return code;
}
#define P_LEN 256
/* 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;
- BYTE ciResponse[P_RESP_LEN]; /* Unicode representation */
- BYTE csResponse[P_RESP_LEN]; /* ANSI representation */
- WCHAR accountNameW[P_LEN];
- WCHAR primaryDomainW[P_LEN];
- WCHAR workstationW[MAX_COMPUTERNAME_LENGTH + 1];
- TOKEN_GROUPS tgroups;
- TOKEN_SOURCE tsource;
+ MSV1_0_LM20_LOGON lmlogon;
+ BYTE ciResponse[P_RESP_LEN]; /* Unicode representation */
+ BYTE csResponse[P_RESP_LEN]; /* ANSI representation */
+ WCHAR accountNameW[P_LEN];
+ WCHAR primaryDomainW[P_LEN];
+ WCHAR workstationW[MAX_COMPUTERNAME_LENGTH + 1];
+ TOKEN_GROUPS tgroups;
+ TOKEN_SOURCE tsource;
};
-long smb_AuthenticateUserLM(smb_vc_t *vcp, char * accountName, char * primaryDomain, char * ciPwd, unsigned ciPwdLength, char * csPwd, unsigned csPwdLength) {
-
- NTSTATUS nts, ntsEx;
- struct Lm20AuthBlob lmAuth;
- PMSV1_0_LM20_LOGON_PROFILE lmprofilep;
- QUOTA_LIMITS quotaLimits;
- DWORD size;
- ULONG lmprofilepSize;
- LUID lmSession;
- HANDLE lmToken;
-
- OutputDebugF("In smb_AuthenticateUser for user [%s] domain [%s]", accountName, primaryDomain);
- OutputDebugF("ciPwdLength is %d and csPwdLength is %d", ciPwdLength, csPwdLength);
-
- if (ciPwdLength > P_RESP_LEN || csPwdLength > P_RESP_LEN) {
- OutputDebugF("ciPwdLength or csPwdLength is too long");
- return CM_ERROR_BADPASSWORD;
- }
+long smb_AuthenticateUserLM(smb_vc_t *vcp, char * accountName, char * primaryDomain, char * ciPwd, unsigned ciPwdLength, char * csPwd, unsigned csPwdLength)
+{
+ NTSTATUS nts, ntsEx;
+ struct Lm20AuthBlob lmAuth;
+ PMSV1_0_LM20_LOGON_PROFILE lmprofilep;
+ QUOTA_LIMITS quotaLimits;
+ DWORD size;
+ ULONG lmprofilepSize;
+ LUID lmSession;
+ HANDLE lmToken;
+
+ OutputDebugF("In smb_AuthenticateUser for user [%s] domain [%s]", accountName, primaryDomain);
+ OutputDebugF("ciPwdLength is %d and csPwdLength is %d", ciPwdLength, csPwdLength);
+
+ if (ciPwdLength > P_RESP_LEN || csPwdLength > P_RESP_LEN) {
+ OutputDebugF("ciPwdLength or csPwdLength is too long");
+ return CM_ERROR_BADPASSWORD;
+ }
- memset(&lmAuth,0,sizeof(lmAuth));
+ memset(&lmAuth,0,sizeof(lmAuth));
- lmAuth.lmlogon.MessageType = MsV1_0NetworkLogon;
+ lmAuth.lmlogon.MessageType = MsV1_0NetworkLogon;
- lmAuth.lmlogon.LogonDomainName.Buffer = lmAuth.primaryDomainW;
- mbstowcs(lmAuth.primaryDomainW, primaryDomain, P_LEN);
- lmAuth.lmlogon.LogonDomainName.Length = wcslen(lmAuth.primaryDomainW) * sizeof(WCHAR);
- lmAuth.lmlogon.LogonDomainName.MaximumLength = P_LEN * sizeof(WCHAR);
-
- lmAuth.lmlogon.UserName.Buffer = lmAuth.accountNameW;
- mbstowcs(lmAuth.accountNameW, accountName, P_LEN);
- lmAuth.lmlogon.UserName.Length = wcslen(lmAuth.accountNameW) * sizeof(WCHAR);
- lmAuth.lmlogon.UserName.MaximumLength = P_LEN * sizeof(WCHAR);
-
- lmAuth.lmlogon.Workstation.Buffer = lmAuth.workstationW;
- lmAuth.lmlogon.Workstation.MaximumLength = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR);
- size = MAX_COMPUTERNAME_LENGTH + 1;
- GetComputerNameW(lmAuth.workstationW, &size);
+ lmAuth.lmlogon.LogonDomainName.Buffer = lmAuth.primaryDomainW;
+ mbstowcs(lmAuth.primaryDomainW, primaryDomain, P_LEN);
+ lmAuth.lmlogon.LogonDomainName.Length = wcslen(lmAuth.primaryDomainW) * sizeof(WCHAR);
+ lmAuth.lmlogon.LogonDomainName.MaximumLength = P_LEN * sizeof(WCHAR);
+
+ lmAuth.lmlogon.UserName.Buffer = lmAuth.accountNameW;
+ mbstowcs(lmAuth.accountNameW, accountName, P_LEN);
+ lmAuth.lmlogon.UserName.Length = wcslen(lmAuth.accountNameW) * sizeof(WCHAR);
+ lmAuth.lmlogon.UserName.MaximumLength = P_LEN * sizeof(WCHAR);
+
+ lmAuth.lmlogon.Workstation.Buffer = lmAuth.workstationW;
+ lmAuth.lmlogon.Workstation.MaximumLength = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR);
+ size = MAX_COMPUTERNAME_LENGTH + 1;
+ GetComputerNameW(lmAuth.workstationW, &size);
lmAuth.lmlogon.Workstation.Length = wcslen(lmAuth.workstationW) * sizeof(WCHAR);
- memcpy(lmAuth.lmlogon.ChallengeToClient, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
-
- lmAuth.lmlogon.CaseInsensitiveChallengeResponse.Buffer = lmAuth.ciResponse;
- lmAuth.lmlogon.CaseInsensitiveChallengeResponse.Length = ciPwdLength;
- lmAuth.lmlogon.CaseInsensitiveChallengeResponse.MaximumLength = P_RESP_LEN;
- memcpy(lmAuth.ciResponse, ciPwd, ciPwdLength);
-
- lmAuth.lmlogon.CaseSensitiveChallengeResponse.Buffer = lmAuth.csResponse;
- lmAuth.lmlogon.CaseSensitiveChallengeResponse.Length = csPwdLength;
- lmAuth.lmlogon.CaseSensitiveChallengeResponse.MaximumLength = P_RESP_LEN;
- memcpy(lmAuth.csResponse, csPwd, csPwdLength);
-
- lmAuth.lmlogon.ParameterControl = 0;
-
- lmAuth.tgroups.GroupCount = 0;
- lmAuth.tgroups.Groups[0].Sid = NULL;
- lmAuth.tgroups.Groups[0].Attributes = 0;
-
- lmAuth.tsource.SourceIdentifier.HighPart = 0;
- lmAuth.tsource.SourceIdentifier.LowPart = (DWORD) vcp;
- strcpy(lmAuth.tsource.SourceName,"OpenAFS"); /* 8 char limit */
-
- nts = LsaLogonUser(
- smb_lsaHandle,
- &smb_lsaLogonOrigin,
- Network, /*3*/
- smb_lsaSecPackage,
- &lmAuth,
- sizeof(lmAuth),
- &lmAuth.tgroups,
- &lmAuth.tsource,
- &lmprofilep,
- &lmprofilepSize,
- &lmSession,
- &lmToken,
- "aLimits,
- &ntsEx);
-
- OutputDebugF("Return from LsaLogonUser is 0x%lX", nts);
- OutputDebugF("Extended status is 0x%lX", ntsEx);
-
- if (nts == ERROR_SUCCESS) {
- /* free the token */
- LsaFreeReturnBuffer(lmprofilep);
+ memcpy(lmAuth.lmlogon.ChallengeToClient, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
+
+ lmAuth.lmlogon.CaseInsensitiveChallengeResponse.Buffer = lmAuth.ciResponse;
+ lmAuth.lmlogon.CaseInsensitiveChallengeResponse.Length = ciPwdLength;
+ lmAuth.lmlogon.CaseInsensitiveChallengeResponse.MaximumLength = P_RESP_LEN;
+ memcpy(lmAuth.ciResponse, ciPwd, ciPwdLength);
+
+ lmAuth.lmlogon.CaseSensitiveChallengeResponse.Buffer = lmAuth.csResponse;
+ lmAuth.lmlogon.CaseSensitiveChallengeResponse.Length = csPwdLength;
+ lmAuth.lmlogon.CaseSensitiveChallengeResponse.MaximumLength = P_RESP_LEN;
+ memcpy(lmAuth.csResponse, csPwd, csPwdLength);
+
+ lmAuth.lmlogon.ParameterControl = 0;
+
+ lmAuth.tgroups.GroupCount = 0;
+ lmAuth.tgroups.Groups[0].Sid = NULL;
+ lmAuth.tgroups.Groups[0].Attributes = 0;
+
+ lmAuth.tsource.SourceIdentifier.HighPart = 0;
+ lmAuth.tsource.SourceIdentifier.LowPart = (DWORD) vcp;
+ strcpy(lmAuth.tsource.SourceName,"OpenAFS"); /* 8 char limit */
+
+ nts = LsaLogonUser( smb_lsaHandle,
+ &smb_lsaLogonOrigin,
+ Network, /*3*/
+ smb_lsaSecPackage,
+ &lmAuth,
+ sizeof(lmAuth),
+ &lmAuth.tgroups,
+ &lmAuth.tsource,
+ &lmprofilep,
+ &lmprofilepSize,
+ &lmSession,
+ &lmToken,
+ "aLimits,
+ &ntsEx);
+
+ if (nts != STATUS_SUCCESS || ntsEx != STATUS_SUCCESS)
+ osi_Log2(smb_logp,"LsaLogonUser failure: nts %u ntsEx %u",
+ nts, ntsEx);
+
+ OutputDebugF("Return from LsaLogonUser is 0x%lX", nts);
+ OutputDebugF("Extended status is 0x%lX", ntsEx);
+
+ if (nts == ERROR_SUCCESS) {
+ /* free the token */
+ LsaFreeReturnBuffer(lmprofilep);
CloseHandle(lmToken);
- return 0;
- } else {
- /* No AFS for you */
- if (nts == 0xC000015BL)
- return CM_ERROR_BADLOGONTYPE;
- else /* our catchall is a bad password though we could be more specific */
- return CM_ERROR_BADPASSWORD;
- }
+ return 0;
+ } else {
+ /* No AFS for you */
+ if (nts == 0xC000015BL)
+ 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(char * usern, const char * accountName, const char * domainName) {
-
- char * atsign;
- const char * domain;
-
- /* check if we have sane input */
- if ((strlen(accountName) + strlen(domainName) + 1) > SMB_MAX_USERNAME_LENGTH)
- return 1;
-
- /* we could get : [accountName][domainName]
- [user][domain]
- [user@domain][]
- [user][]/[user][?]
- [][]/[][?] */
-
- atsign = strchr(accountName, '@');
-
- if (atsign) /* [user@domain][] -> [user@domain][domain] */
- domain = atsign + 1;
- else
- domain = domainName;
-
- /* if for some reason the client doesn't know what domain to use,
- 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
- when a non-empty username would be supplied with an anonymous domain, but *shrug* */
- strcpy(usern,accountName);
- else {
- /* TODO: what about WIN.MIT.EDU\user vs. WIN\user? */
- strcpy(usern,domain);
- strcat(usern,"\\");
- if (atsign)
- strncat(usern,accountName,atsign - accountName);
- else
- strcat(usern,accountName);
- }
+long smb_GetNormalizedUsername(char * usern, const char * accountName, const char * domainName)
+{
+ char * atsign;
+ const char * domain;
+
+ /* check if we have sane input */
+ if ((strlen(accountName) + strlen(domainName) + 1) > SMB_MAX_USERNAME_LENGTH)
+ return 1;
+
+ /* we could get : [accountName][domainName]
+ [user][domain]
+ [user@domain][]
+ [user][]/[user][?]
+ [][]/[][?] */
- strlwr(usern);
+ atsign = strchr(accountName, '@');
- return 0;
+ if (atsign) /* [user@domain][] -> [user@domain][domain] */
+ domain = atsign + 1;
+ else
+ domain = domainName;
+
+ /* if for some reason the client doesn't know what domain to use,
+ 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
+ when a non-empty username would be supplied with an anonymous domain, but *shrug* */
+ strcpy(usern,accountName);
+ else {
+ /* TODO: what about WIN.MIT.EDU\user vs. WIN\user? */
+ strcpy(usern,domain);
+ strcat(usern,"\\");
+ if (atsign)
+ strncat(usern,accountName,atsign - accountName);
+ else
+ strcat(usern,accountName);
+ }
+
+ strlwr(usern);
+
+ return 0;
}
-/* When using SMB auth, all SMB sessions have to pass through here first to
- * authenticate the user.
- * Caveat: If not use the SMB auth the protocol does not require sending a
- * session setup packet, which means that we can't rely on a UID in subsequent
- * packets. Though in practice we get one anyway.
+/* When using SMB auth, all SMB sessions have to pass through here
+ * 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
+ * UID in subsequent packets. Though in practice we get one anyway.
*/
long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
/* extended authentication */
char *secBlobIn;
int secBlobInLength;
+
+ OutputDebugF("NT Session Setup: Extended");
if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) {
caps = smb_GetSMBParm(inp,10) | (((unsigned long) smb_GetSMBParm(inp,11)) << 16);
char *primaryDomain;
int datalen;
+ if (smb_authType == SMB_AUTH_NTLM)
+ OutputDebugF("NT Session Setup: NTLM");
+ else
+ OutputDebugF("NT Session Setup: None");
+
/* TODO: parse for extended auth as well */
ciPwdLength = smb_GetSMBParm(inp, 7); /* case insensitive password length */
csPwdLength = smb_GetSMBParm(inp, 8); /* case sensitive password length */
accountName = smb_ParseString(tp, &tp);
primaryDomain = smb_ParseString(tp, NULL);
+ OutputDebugF("Account Name: %s",accountName);
+ OutputDebugF("Primary Domain: %s", primaryDomain);
+ OutputDebugF("Case Sensitive Password: %s", csPwd && csPwd[0] ? "yes" : "no");
+ OutputDebugF("Case Insensitive Password: %s", ciPwd && ciPwd[0] ? "yes" : "no");
+
if (smb_GetNormalizedUsername(usern, accountName, primaryDomain)) {
/* shouldn't happen */
code = CM_ERROR_BADSMB;
if (smb_authType == SMB_AUTH_NTLM) {
code = smb_AuthenticateUserLM(vcp, accountName, primaryDomain, ciPwd, ciPwdLength, csPwd, csPwdLength);
+ if ( code )
+ OutputDebugF("LM authentication failed [%d]", code);
+ else
+ OutputDebugF("LM authentication succeeded");
}
}
} else { /* V3 */
unsigned ciPwdLength;
char *ciPwd;
- char *accountName;
- char *primaryDomain;
+ char *accountName;
+ char *primaryDomain;
- ciPwdLength = smb_GetSMBParm(inp, 7);
+ switch ( smb_authType ) {
+ case SMB_AUTH_EXTENDED:
+ OutputDebugF("V3 Session Setup: Extended");
+ break;
+ case SMB_AUTH_NTLM:
+ OutputDebugF("V3 Session Setup: NTLM");
+ break;
+ default:
+ OutputDebugF("V3 Session Setup: None");
+ }
+ ciPwdLength = smb_GetSMBParm(inp, 7);
tp = smb_GetSMBData(inp, NULL);
- ciPwd = tp;
- tp += ciPwdLength;
+ ciPwd = tp;
+ tp += ciPwdLength;
+
+ accountName = smb_ParseString(tp, &tp);
+ primaryDomain = smb_ParseString(tp, NULL);
- accountName = smb_ParseString(tp, &tp);
- primaryDomain = smb_ParseString(tp, NULL);
+ OutputDebugF("Account Name: %s",accountName);
+ OutputDebugF("Primary Domain: %s", primaryDomain);
+ OutputDebugF("Case Insensitive Password: %s", ciPwd && ciPwd[0] ? "yes" : "no");
- if ( smb_GetNormalizedUsername(usern, accountName, primaryDomain)) {
- /* shouldn't happen */
- code = CM_ERROR_BADSMB;
+ if ( smb_GetNormalizedUsername(usern, accountName, primaryDomain)) {
+ /* shouldn't happen */
+ code = CM_ERROR_BADSMB;
goto after_read_packet;
- }
+ }
/* even if we wanted extended auth, if we only negotiated V3, we have to fallback
* to NTLM.
*/
- if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
- code = smb_AuthenticateUserLM(vcp,accountName,primaryDomain,ciPwd,ciPwdLength,"",0);
- }
- }
+ if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+ code = smb_AuthenticateUserLM(vcp,accountName,primaryDomain,ciPwd,ciPwdLength,"",0);
+ if ( code )
+ OutputDebugF("LM authentication failed [%d]", code);
+ else
+ OutputDebugF("LM authentication succeeded");
+ }
+ }
after_read_packet:
- /* note down that we received a session setup X and set the capabilities flag */
- if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) {
- lock_ObtainMutex(&vcp->mx);
- vcp->flags |= SMB_VCFLAG_SESSX_RCVD;
+ /* note down that we received a session setup X and set the capabilities flag */
+ if (!(vcp->flags & SMB_VCFLAG_SESSX_RCVD)) {
+ lock_ObtainMutex(&vcp->mx);
+ vcp->flags |= SMB_VCFLAG_SESSX_RCVD;
/* for the moment we can only deal with NTSTATUS */
if (caps & NTNEGOTIATE_CAPABILITY_NTSTATUS) {
vcp->flags |= SMB_VCFLAG_STATUS32;
- }
- lock_ReleaseMutex(&vcp->mx);
- }
+ }
+ lock_ReleaseMutex(&vcp->mx);
+ }
- /* code would be non-zero if there was an authentication failure.
- Ideally we would like to invalidate the uid for this session or break
- early to avoid accidently stealing someone else's tokens. */
+ /* code would be non-zero if there was an authentication failure.
+ Ideally we would like to invalidate the uid for this session or break
+ early to avoid accidently stealing someone else's tokens. */
- if (code) {
- return code;
- }
+ if (code) {
+ return code;
+ }
- OutputDebugF("Received username=[%s]", usern);
+ OutputDebugF("Received username=[%s]", usern);
/* On Windows 2000, this function appears to be called more often than
it is expected to be called. This resulted in multiple smb_user_t
if (s1 == NULL) {s1 = s2; s2 = " ";}
osi_Log4(smb_logp, "SMB3 user logoffX uid %d name %s%s%s", uidp->userID,
- osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "), s1, s2);
+ osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "),
+ osi_LogSaveString(smb_logp,s1), osi_LogSaveString(smb_logp,s2));
lock_ObtainMutex(&uidp->mx);
uidp->flags |= SMB_USERFLAG_DELETE;
}
#define SMB_SUPPORT_SEARCH_BITS 0x0001
+#define SMB_SHARE_IS_IN_DFS 0x0002
long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
tp = smb_GetSMBData(inp, NULL);
passwordp = smb_ParseString(tp, &tp);
pathp = smb_ParseString(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
servicep = smb_ParseString(tp, &tp);
tp = strrchr(pathp, '\\');
tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
- if(!ipc) {
+ if (!ipc) {
uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
if (uidp)
if (vcp->flags & SMB_VCFLAG_USENT)
{
int policy = smb_FindShareCSCPolicy(shareName);
- smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS | (policy << 2));
+ smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS |
+#ifdef DFS_SUPPORT
+ SMB_SHARE_IS_IN_DFS |
+#endif
+ (policy << 2));
}
} else {
smb_SetSMBParm(outp, 2, 0);
lock_ObtainMutex(&tidp->mx);
tidp->userp = userp;
tidp->pathname = sharePath;
- if(ipc) tidp->flags |= SMB_TIDFLAG_IPC;
+ if (ipc)
+ tidp->flags |= SMB_TIDFLAG_IPC;
lock_ReleaseMutex(&tidp->mx);
smb_ReleaseTID(tidp);
((smb_t *)inp)->tid = newTid;
tp = smb_GetSMBData(outp, NULL);
if (!ipc) {
+ /* XXX - why is this a drive letter? */
*tp++ = 'A';
*tp++ = ':';
*tp++ = 0;
- smb_SetSMBDataLength(outp, 3);
+ *tp++ = 'N';
+ *tp++ = 'T';
+ *tp++ = 'F';
+ *tp++ = 'S';
+ *tp++ = 0;
+ smb_SetSMBDataLength(outp, 8);
} else {
strcpy(tp, "IPC");
smb_SetSMBDataLength(outp, 4);
/* free a tran2 packet; must be called with smb_globalLock held */
void smb_FreeTran2Packet(smb_tran2Packet_t *t2p)
{
- if (t2p->vcp) smb_ReleaseVC(t2p->vcp);
- if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) {
- if (t2p->parmsp)
- free(t2p->parmsp);
- if (t2p->datap)
- free(t2p->datap);
- }
+ if (t2p->vcp)
+ smb_ReleaseVC(t2p->vcp);
+ if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) {
+ if (t2p->parmsp)
+ free(t2p->parmsp);
+ if (t2p->datap)
+ free(t2p->datap);
+ }
free(t2p);
}
smb_t *smbp;
unsigned short errCode;
unsigned char errClass;
- unsigned long NTStatus;
+ unsigned long NTStatus;
if (vcp->flags & SMB_VCFLAG_STATUS32)
- smb_MapNTError(code, &NTStatus);
- else
- smb_MapCoreError(code, vcp, &errCode, &errClass);
+ smb_MapNTError(code, &NTStatus);
+ else
+ smb_MapCoreError(code, vcp, &errCode, &errClass);
smb_FormatResponsePacket(vcp, NULL, tp);
smbp = (smb_t *) tp;
- /* We can handle long names */
- if (vcp->flags & SMB_VCFLAG_USENT)
- smbp->flg2 |= 0x40; /* IS_LONG_NAME */
+ /* 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->mid = t2p->mid;
smbp->pid = t2p->pid;
smbp->uid = t2p->uid;
- smbp->res[0] = t2p->res[0];
- if (vcp->flags & SMB_VCFLAG_STATUS32) {
- 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 |= 0x4000;
- }
- else {
+ smbp->res[0] = t2p->res[0];
+ if (vcp->flags & SMB_VCFLAG_STATUS32) {
+ 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 {
smbp->rcls = errClass;
- smbp->errLow = (unsigned char) (errCode & 0xff);
- smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
- }
+ smbp->errLow = (unsigned char) (errCode & 0xff);
+ smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
+ }
/* send packet */
smb_SendPacket(vcp, tp);
{
smb_t *smbp;
unsigned short parmOffset;
- unsigned short dataOffset;
- unsigned short totalLength;
- unsigned short dataAlign;
+ unsigned short dataOffset;
+ unsigned short totalLength;
+ unsigned short dataAlign;
char *datap;
-
+
smb_FormatResponsePacket(vcp, NULL, tp);
smbp = (smb_t *) tp;
- /* We can handle long names */
- if (vcp->flags & SMB_VCFLAG_USENT)
- smbp->flg2 |= 0x40; /* IS_LONG_NAME */
+ /* 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->mid = t2p->mid;
smbp->pid = t2p->pid;
smbp->uid = t2p->uid;
- smbp->res[0] = t2p->res[0];
+ smbp->res[0] = t2p->res[0];
totalLength = 1 + t2p->totalData + t2p->totalParms;
smb_SetSMBParm(tp, 1, t2p->totalData); /* data bytes */
smb_SetSMBParm(tp, 2, 0); /* reserved */
smb_SetSMBParm(tp, 3, t2p->totalParms); /* parm bytes in this packet */
- parmOffset = 10*2 + 35; /* parm offset in packet */
- parmOffset++; /* round to even */
+ parmOffset = 10*2 + 35; /* parm offset in packet */
+ parmOffset++; /* round to even */
smb_SetSMBParm(tp, 4, parmOffset); /* 11 parm words plus *
* hdr, bcc and wct */
smb_SetSMBParm(tp, 5, 0); /* parm displacement */
smb_SetSMBParm(tp, 6, t2p->totalData); /* data in this packet */
- dataOffset = parmOffset + t2p->oldTotalParms;
- dataAlign = dataOffset & 2; /* quad-align */
- dataOffset += dataAlign;
+ dataOffset = parmOffset + t2p->oldTotalParms;
+ dataAlign = dataOffset & 2; /* quad-align */
+ dataOffset += dataAlign;
smb_SetSMBParm(tp, 7, dataOffset); /* offset of data */
smb_SetSMBParm(tp, 8, 0); /* data displacement */
smb_SetSMBParm(tp, 9, 0); /* low: setup word count *
- * high: resvd */
+ * high: resvd */
datap = smb_GetSMBData(tp, NULL);
- *datap++ = 0; /* we rounded to even */
+ *datap++ = 0; /* we rounded to even */
- totalLength += dataAlign;
+ totalLength += dataAlign;
smb_SetSMBDataLength(tp, totalLength);
/* next, send the datagram */
int parmCount;
int dataCount;
int firstPacket;
- int rapOp;
+ int rapOp;
long code = 0;
- /* We sometimes see 0 word count. What to do? */
- if (*inp->wctp == 0) {
+ /* We sometimes see 0 word count. What to do? */
+ if (*inp->wctp == 0) {
#ifndef DJGPP
- HANDLE h;
- char *ptbuf[1];
+ HANDLE h;
+ char *ptbuf[1];
- osi_Log0(smb_logp, "TRANSACTION word count = 0");
+ osi_Log0(smb_logp, "TRANSACTION word count = 0");
- h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
- ptbuf[0] = "Transaction2 word count = 0";
- ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
- 1, inp->ncb_length, ptbuf, inp);
- DeregisterEventSource(h);
+ h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
+ ptbuf[0] = "Transaction2 word count = 0";
+ ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
+ 1, inp->ncb_length, ptbuf, inp);
+ DeregisterEventSource(h);
#else /* DJGPP */
- osi_Log0(smb_logp, "TRANSACTION word count = 0");
+ osi_Log0(smb_logp, "TRANSACTION word count = 0");
#endif /* !DJGPP */
smb_SetSMBDataLength(outp, 0);
smb_SendPacket(vcp, outp);
- return 0;
- }
+ return 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);
+ /* find the packet we're reassembling */
+ lock_ObtainWrite(&smb_globalLock);
asp = smb_FindTran2Packet(vcp, inp);
if (!asp) {
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;
+ if (firstPacket) {
+ parmDisp = dataDisp = 0;
parmOffset = smb_GetSMBParm(inp, 10);
dataOffset = smb_GetSMBParm(inp, 12);
parmCount = smb_GetSMBParm(inp, 9);
dataCount = smb_GetSMBParm(inp, 11);
- asp->maxReturnParms = smb_GetSMBParm(inp, 2);
+ 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);
+ osi_Log3(smb_logp, "SMB3 received Trans init packet total data %d, cur data %d, max return data %d",
+ totalData, dataCount, asp->maxReturnData);
}
else {
parmDisp = smb_GetSMBParm(inp, 4);
asp->curParms > 0 &&
asp->totalData <= asp->curData &&
asp->totalParms <= asp->curParms) {
- /* we've received it all */
+ /* we've received it all */
lock_ObtainWrite(&smb_globalLock);
- osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
+ osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
lock_ReleaseWrite(&smb_globalLock);
/* now dispatch it */
- rapOp = asp->parmsp[0];
+ rapOp = asp->parmsp[0];
if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES && smb_rapDispatchTable[rapOp].procp) {
osi_LogEvent("AFS-Dispatch-RAP[%s]",myCrt_RapDispatch(rapOp),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
share names, but we don't support unicode yet. */
typedef struct smb_rap_share_info_0 {
- char shi0_netname[13];
+ char shi0_netname[13];
} smb_rap_share_info_0_t;
typedef struct smb_rap_share_info_1 {
- char shi1_netname[13];
- char shi1_pad;
- WORD shi1_type;
- DWORD shi1_remark; /* char *shi1_remark; data offset */
+ char shi1_netname[13];
+ char shi1_pad;
+ WORD shi1_type;
+ DWORD shi1_remark; /* char *shi1_remark; data offset */
} smb_rap_share_info_1_t;
typedef struct smb_rap_share_info_2 {
- char shi2_netname[13];
- char shi2_pad;
- unsigned short shi2_type;
- DWORD shi2_remark; /* char *shi2_remark; data offset */
- unsigned short shi2_permissions;
- unsigned short shi2_max_uses;
- unsigned short shi2_current_uses;
- DWORD shi2_path; /* char *shi2_path; data offset */
- unsigned short shi2_passwd[9];
- unsigned short shi2_pad2;
+ char shi2_netname[13];
+ char shi2_pad;
+ unsigned short shi2_type;
+ DWORD shi2_remark; /* char *shi2_remark; data offset */
+ unsigned short shi2_permissions;
+ unsigned short shi2_max_uses;
+ unsigned short shi2_current_uses;
+ DWORD shi2_path; /* char *shi2_path; data offset */
+ unsigned short shi2_passwd[9];
+ unsigned short shi2_pad2;
} smb_rap_share_info_2_t;
#define SMB_RAP_MAX_SHARES 512
typedef struct smb_rap_share_list {
- int cShare;
- int maxShares;
- smb_rap_share_info_0_t * shares;
+ int cShare;
+ int maxShares;
+ smb_rap_share_info_0_t * shares;
} smb_rap_share_list_t;
int smb_rapCollectSharesProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp) {
- smb_rap_share_list_t * sp;
- char * name;
+ smb_rap_share_list_t * sp;
+ char * name;
- name = dep->name;
+ name = dep->name;
- if(name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2])))
- return 0; /* skip over '.' and '..' */
+ if (name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2])))
+ return 0; /* skip over '.' and '..' */
- sp = (smb_rap_share_list_t *) vrockp;
+ sp = (smb_rap_share_list_t *) vrockp;
- strncpy(sp->shares[sp->cShare].shi0_netname, name, 12);
- sp->shares[sp->cShare].shi0_netname[12] = 0;
+ strncpy(sp->shares[sp->cShare].shi0_netname, name, 12);
+ sp->shares[sp->cShare].shi0_netname[12] = 0;
- sp->cShare++;
+ sp->cShare++;
- if(sp->cShare >= sp->maxShares)
- return CM_ERROR_STOPNOW;
- else
- return 0;
-}
+ if (sp->cShare >= sp->maxShares)
+ return CM_ERROR_STOPNOW;
+ else
+ return 0;
+}
long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
{
- smb_tran2Packet_t *outp;
- unsigned short * tp;
- int len;
- int infoLevel;
- int bufsize;
- int outParmsTotal; /* total parameter bytes */
- int outDataTotal; /* total data bytes */
- int code = 0;
- DWORD rv;
- DWORD allSubmount;
- USHORT nShares;
- DWORD nRegShares;
- DWORD nSharesRet;
- HKEY hkParam;
- HKEY hkSubmount = NULL;
- smb_rap_share_info_1_t * shares;
- USHORT cshare = 0;
- char * cstrp;
- char thisShare[256];
- int i,j;
- int nonrootShares;
- smb_rap_share_list_t rootShares;
- cm_req_t req;
- cm_user_t * userp;
- osi_hyper_t thyper;
-
- tp = p->parmsp + 1; /* skip over function number (always 0) */
- (void) smb_ParseString((char *) tp, (char **) &tp); /* skip over parm descriptor */
- (void) smb_ParseString((char *) tp, (char **) &tp); /* skip over data descriptor */
- infoLevel = tp[0];
+ smb_tran2Packet_t *outp;
+ unsigned short * tp;
+ int len;
+ int infoLevel;
+ int bufsize;
+ int outParmsTotal; /* total parameter bytes */
+ int outDataTotal; /* total data bytes */
+ int code = 0;
+ DWORD rv;
+ DWORD allSubmount;
+ USHORT nShares;
+ DWORD nRegShares;
+ DWORD nSharesRet;
+ HKEY hkParam;
+ HKEY hkSubmount = NULL;
+ smb_rap_share_info_1_t * shares;
+ USHORT cshare = 0;
+ char * cstrp;
+ char thisShare[256];
+ int i,j;
+ int nonrootShares;
+ smb_rap_share_list_t rootShares;
+ cm_req_t req;
+ cm_user_t * userp;
+ osi_hyper_t thyper;
+
+ tp = p->parmsp + 1; /* skip over function number (always 0) */
+ (void) smb_ParseString((char *) tp, (char **) &tp); /* skip over parm descriptor */
+ (void) smb_ParseString((char *) tp, (char **) &tp); /* skip over data descriptor */
+ infoLevel = tp[0];
bufsize = tp[1];
- if(infoLevel != 1) {
- return CM_ERROR_INVAL;
- }
+ if (infoLevel != 1) {
+ return CM_ERROR_INVAL;
+ }
- /* first figure out how many shares there are */
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0,
- KEY_QUERY_VALUE, &hkParam);
- if (rv == ERROR_SUCCESS) {
+ /* first figure out how many shares there are */
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0,
+ KEY_QUERY_VALUE, &hkParam);
+ if (rv == ERROR_SUCCESS) {
len = sizeof(allSubmount);
rv = RegQueryValueEx(hkParam, "AllSubmount", NULL, NULL,
- (BYTE *) &allSubmount, &len);
- if (rv != ERROR_SUCCESS || allSubmount != 0) {
- allSubmount = 1;
- }
+ (BYTE *) &allSubmount, &len);
+ if (rv != ERROR_SUCCESS || allSubmount != 0) {
+ allSubmount = 1;
+ }
RegCloseKey (hkParam);
- }
+ }
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\Submounts",
- 0, KEY_QUERY_VALUE, &hkSubmount);
- if (rv == ERROR_SUCCESS) {
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
+ 0, KEY_QUERY_VALUE, &hkSubmount);
+ if (rv == ERROR_SUCCESS) {
rv = RegQueryInfoKey(hkSubmount, NULL, NULL, NULL, NULL,
- NULL, NULL, &nRegShares, NULL, NULL, NULL, NULL);
- if (rv != ERROR_SUCCESS)
- nRegShares = 0;
- } else {
- hkSubmount = NULL;
- }
+ NULL, NULL, &nRegShares, NULL, NULL, NULL, NULL);
+ if (rv != ERROR_SUCCESS)
+ nRegShares = 0;
+ } else {
+ hkSubmount = NULL;
+ }
- /* fetch the root shares */
- rootShares.maxShares = SMB_RAP_MAX_SHARES;
- rootShares.cShare = 0;
- rootShares.shares = malloc( sizeof(smb_rap_share_info_0_t) * SMB_RAP_MAX_SHARES );
+ /* fetch the root shares */
+ rootShares.maxShares = SMB_RAP_MAX_SHARES;
+ rootShares.cShare = 0;
+ rootShares.shares = malloc( sizeof(smb_rap_share_info_0_t) * SMB_RAP_MAX_SHARES );
- cm_InitReq(&req);
+ cm_InitReq(&req);
- userp = smb_GetTran2User(vcp,p);
+ userp = smb_GetTran2User(vcp,p);
- thyper.HighPart = 0;
- thyper.LowPart = 0;
+ thyper.HighPart = 0;
+ thyper.LowPart = 0;
- cm_HoldSCache(cm_rootSCachep);
- cm_ApplyDir(cm_rootSCachep, smb_rapCollectSharesProc, &rootShares, &thyper, userp, &req, NULL);
- cm_ReleaseSCache(cm_rootSCachep);
+ cm_HoldSCache(cm_data.rootSCachep);
+ cm_ApplyDir(cm_data.rootSCachep, smb_rapCollectSharesProc, &rootShares, &thyper, userp, &req, NULL);
+ cm_ReleaseSCache(cm_data.rootSCachep);
- cm_ReleaseUser(userp);
+ cm_ReleaseUser(userp);
- nShares = rootShares.cShare + nRegShares + allSubmount;
+ nShares = rootShares.cShare + nRegShares + allSubmount;
#define REMARK_LEN 1
- outParmsTotal = 8; /* 4 dwords */
- outDataTotal = (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nShares ;
- if(outDataTotal > bufsize) {
- nSharesRet = bufsize / (sizeof(smb_rap_share_info_1_t) + REMARK_LEN);
- outDataTotal = (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nSharesRet;
- }
- else {
- nSharesRet = nShares;
- }
+ outParmsTotal = 8; /* 4 dwords */
+ outDataTotal = (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nShares ;
+ if(outDataTotal > bufsize) {
+ nSharesRet = bufsize / (sizeof(smb_rap_share_info_1_t) + REMARK_LEN);
+ outDataTotal = (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nSharesRet;
+ }
+ else {
+ nSharesRet = nShares;
+ }
- outp = smb_GetTran2ResponsePacket(vcp, p, op, outParmsTotal, outDataTotal);
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, outParmsTotal, outDataTotal);
- /* now for the submounts */
+ /* now for the submounts */
shares = (smb_rap_share_info_1_t *) outp->datap;
- cstrp = outp->datap + sizeof(smb_rap_share_info_1_t) * nSharesRet;
+ cstrp = outp->datap + sizeof(smb_rap_share_info_1_t) * nSharesRet;
- memset(outp->datap, 0, (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nSharesRet);
+ memset(outp->datap, 0, (sizeof(smb_rap_share_info_1_t) + REMARK_LEN) * nSharesRet);
- if(allSubmount) {
- strcpy( shares[cshare].shi1_netname, "all" );
- shares[cshare].shi1_remark = cstrp - outp->datap;
- /* type and pad are zero already */
- cshare++;
- cstrp+=REMARK_LEN;
- }
+ if (allSubmount) {
+ strcpy( shares[cshare].shi1_netname, "all" );
+ shares[cshare].shi1_remark = cstrp - outp->datap;
+ /* type and pad are zero already */
+ cshare++;
+ cstrp+=REMARK_LEN;
+ }
- if(hkSubmount) {
- for(i=0; i < nRegShares && cshare < nSharesRet; i++) {
- len = sizeof(thisShare);
+ if (hkSubmount) {
+ for (i=0; i < nRegShares && cshare < nSharesRet; i++) {
+ len = sizeof(thisShare);
rv = RegEnumValue(hkSubmount, i, thisShare, &len, NULL, NULL, NULL, NULL);
- if(rv == ERROR_SUCCESS && strlen(thisShare) && (!allSubmount || stricmp(thisShare,"all"))) {
- strncpy(shares[cshare].shi1_netname, thisShare, sizeof(shares->shi1_netname)-1);
- shares[cshare].shi1_netname[sizeof(shares->shi1_netname)-1] = 0; /* unfortunate truncation */
- shares[cshare].shi1_remark = cstrp - outp->datap;
- cshare++;
- cstrp+=REMARK_LEN;
- }
- else
- nShares--; /* uncount key */
- }
-
- RegCloseKey(hkSubmount);
- }
+ if (rv == ERROR_SUCCESS && strlen(thisShare) && (!allSubmount || stricmp(thisShare,"all"))) {
+ strncpy(shares[cshare].shi1_netname, thisShare, sizeof(shares->shi1_netname)-1);
+ shares[cshare].shi1_netname[sizeof(shares->shi1_netname)-1] = 0; /* unfortunate truncation */
+ shares[cshare].shi1_remark = cstrp - outp->datap;
+ cshare++;
+ cstrp+=REMARK_LEN;
+ }
+ else
+ nShares--; /* uncount key */
+ }
- nonrootShares = cshare;
+ RegCloseKey(hkSubmount);
+ }
+
+ nonrootShares = cshare;
- for(i=0; i < rootShares.cShare && cshare < nSharesRet; i++) {
+ for (i=0; i < rootShares.cShare && cshare < nSharesRet; i++) {
/* in case there are collisions with submounts, submounts have higher priority */
- for(j=0; j < nonrootShares; j++)
- if(!stricmp(shares[j].shi1_netname, rootShares.shares[i].shi0_netname))
- break;
+ for (j=0; j < nonrootShares; j++)
+ if (!stricmp(shares[j].shi1_netname, rootShares.shares[i].shi0_netname))
+ break;
- if(j < nonrootShares) {
- nShares--; /* uncount */
- continue;
- }
-
- strcpy(shares[cshare].shi1_netname, rootShares.shares[i].shi0_netname);
- shares[cshare].shi1_remark = cstrp - outp->datap;
- cshare++;
- cstrp+=REMARK_LEN;
- }
+ if (j < nonrootShares) {
+ nShares--; /* uncount */
+ continue;
+ }
+
+ strcpy(shares[cshare].shi1_netname, rootShares.shares[i].shi0_netname);
+ shares[cshare].shi1_remark = cstrp - outp->datap;
+ cshare++;
+ cstrp+=REMARK_LEN;
+ }
- outp->parmsp[0] = ((cshare == nShares)? ERROR_SUCCESS : ERROR_MORE_DATA);
- outp->parmsp[1] = 0;
- outp->parmsp[2] = cshare;
- outp->parmsp[3] = nShares;
+ outp->parmsp[0] = ((cshare == nShares)? ERROR_SUCCESS : ERROR_MORE_DATA);
+ outp->parmsp[1] = 0;
+ outp->parmsp[2] = cshare;
+ outp->parmsp[3] = nShares;
- outp->totalData = cstrp - outp->datap;
- outp->totalParms = outParmsTotal;
+ outp->totalData = cstrp - outp->datap;
+ outp->totalParms = outParmsTotal;
- smb_SendTran2Packet(vcp, outp, op);
- smb_FreeTran2Packet(outp);
+ smb_SendTran2Packet(vcp, outp, op);
+ smb_FreeTran2Packet(outp);
- free(rootShares.shares);
+ free(rootShares.shares);
- return code;
+ return code;
}
long smb_ReceiveRAPNetShareGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
{
- smb_tran2Packet_t *outp;
- unsigned short * tp;
- char * shareName;
- BOOL shareFound = FALSE;
- unsigned short infoLevel;
- unsigned short bufsize;
- int totalData;
- int totalParam;
- DWORD len;
- HKEY hkParam;
- HKEY hkSubmount;
- DWORD allSubmount;
- LONG rv;
- long code = 0;
-
- tp = p->parmsp + 1; /* skip over function number (always 1) */
- (void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over param descriptor */
- (void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over data descriptor */
- shareName = smb_ParseString( (char *) tp, (char **) &tp);
+ smb_tran2Packet_t *outp;
+ unsigned short * tp;
+ char * shareName;
+ BOOL shareFound = FALSE;
+ unsigned short infoLevel;
+ unsigned short bufsize;
+ int totalData;
+ int totalParam;
+ DWORD len;
+ HKEY hkParam;
+ HKEY hkSubmount;
+ DWORD allSubmount;
+ LONG rv;
+ long code = 0;
+
+ tp = p->parmsp + 1; /* skip over function number (always 1) */
+ (void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over param descriptor */
+ (void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over data descriptor */
+ shareName = smb_ParseString( (char *) tp, (char **) &tp);
infoLevel = *tp++;
bufsize = *tp++;
- totalParam = 6;
-
- if(infoLevel == 0)
- totalData = sizeof(smb_rap_share_info_0_t);
- else if(infoLevel == 1)
- totalData = sizeof(smb_rap_share_info_1_t) + 1; /* + empty string */
- else if(infoLevel == 2)
- totalData = sizeof(smb_rap_share_info_2_t) + 2; /* + two empty strings */
- else
- return CM_ERROR_INVAL;
-
- outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParam, totalData);
-
- if(!stricmp(shareName,"all")) {
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName, 0,
- KEY_QUERY_VALUE, &hkParam);
- if (rv == ERROR_SUCCESS) {
- len = sizeof(allSubmount);
- rv = RegQueryValueEx(hkParam, "AllSubmount", NULL, NULL,
- (BYTE *) &allSubmount, &len);
- if (rv != ERROR_SUCCESS || allSubmount != 0) {
- allSubmount = 1;
- }
- RegCloseKey (hkParam);
- }
-
- if(allSubmount)
- shareFound = TRUE;
-
- } else {
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\Submounts", 0,
- KEY_QUERY_VALUE, &hkSubmount);
- if(rv == ERROR_SUCCESS) {
+ totalParam = 6;
+
+ if (infoLevel == 0)
+ totalData = sizeof(smb_rap_share_info_0_t);
+ else if(infoLevel == SMB_INFO_STANDARD)
+ totalData = sizeof(smb_rap_share_info_1_t) + 1; /* + empty string */
+ else if(infoLevel == SMB_INFO_QUERY_EA_SIZE)
+ totalData = sizeof(smb_rap_share_info_2_t) + 2; /* + two empty strings */
+ else
+ return CM_ERROR_INVAL;
+
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParam, totalData);
+
+ if(!stricmp(shareName,"all")) {
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0,
+ KEY_QUERY_VALUE, &hkParam);
+ if (rv == ERROR_SUCCESS) {
+ len = sizeof(allSubmount);
+ rv = RegQueryValueEx(hkParam, "AllSubmount", NULL, NULL,
+ (BYTE *) &allSubmount, &len);
+ if (rv != ERROR_SUCCESS || allSubmount != 0) {
+ allSubmount = 1;
+ }
+ RegCloseKey (hkParam);
+ }
+
+ if (allSubmount)
+ shareFound = TRUE;
+
+ } else {
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY "\\Submounts", 0,
+ KEY_QUERY_VALUE, &hkSubmount);
+ if (rv == ERROR_SUCCESS) {
rv = RegQueryValueEx(hkSubmount, shareName, NULL, NULL, NULL, NULL);
- if(rv == ERROR_SUCCESS) {
- shareFound = TRUE;
- }
- RegCloseKey(hkSubmount);
- }
- }
+ if (rv == ERROR_SUCCESS) {
+ shareFound = TRUE;
+ }
+ RegCloseKey(hkSubmount);
+ }
+ }
- if(!shareFound) {
- smb_FreeTran2Packet(outp);
- return CM_ERROR_BADSHARENAME;
- }
+ if (!shareFound) {
+ smb_FreeTran2Packet(outp);
+ return CM_ERROR_BADSHARENAME;
+ }
- memset(outp->datap, 0, totalData);
+ memset(outp->datap, 0, totalData);
- outp->parmsp[0] = 0;
- outp->parmsp[1] = 0;
- outp->parmsp[2] = totalData;
+ outp->parmsp[0] = 0;
+ outp->parmsp[1] = 0;
+ outp->parmsp[2] = totalData;
- if(infoLevel == 0) {
- smb_rap_share_info_0_t * info = (smb_rap_share_info_0_t *) outp->datap;
- strncpy(info->shi0_netname, shareName, sizeof(info->shi0_netname)-1);
- info->shi0_netname[sizeof(info->shi0_netname)-1] = 0;
- } else if(infoLevel == 1) {
- smb_rap_share_info_1_t * info = (smb_rap_share_info_1_t *) outp->datap;
+ if (infoLevel == 0) {
+ smb_rap_share_info_0_t * info = (smb_rap_share_info_0_t *) outp->datap;
+ strncpy(info->shi0_netname, shareName, sizeof(info->shi0_netname)-1);
+ info->shi0_netname[sizeof(info->shi0_netname)-1] = 0;
+ } else if(infoLevel == SMB_INFO_STANDARD) {
+ smb_rap_share_info_1_t * info = (smb_rap_share_info_1_t *) outp->datap;
strncpy(info->shi1_netname, shareName, sizeof(info->shi1_netname)-1);
- info->shi1_netname[sizeof(info->shi1_netname)-1] = 0;
- info->shi1_remark = ((unsigned char *) (info + 1)) - outp->datap;
- /* type and pad are already zero */
- } else { /* infoLevel==2 */
- smb_rap_share_info_2_t * info = (smb_rap_share_info_2_t *) outp->datap;
- strncpy(info->shi2_netname, shareName, sizeof(info->shi2_netname)-1);
- info->shi2_netname[sizeof(info->shi2_netname)-1] = 0;
- info->shi2_remark = ((unsigned char *) (info + 1)) - outp->datap;
+ info->shi1_netname[sizeof(info->shi1_netname)-1] = 0;
+ info->shi1_remark = ((unsigned char *) (info + 1)) - outp->datap;
+ /* type and pad are already zero */
+ } else { /* infoLevel==2 */
+ smb_rap_share_info_2_t * info = (smb_rap_share_info_2_t *) outp->datap;
+ strncpy(info->shi2_netname, shareName, sizeof(info->shi2_netname)-1);
+ info->shi2_netname[sizeof(info->shi2_netname)-1] = 0;
+ info->shi2_remark = ((unsigned char *) (info + 1)) - outp->datap;
info->shi2_permissions = ACCESS_ALL;
- info->shi2_max_uses = (unsigned short) -1;
+ info->shi2_max_uses = (unsigned short) -1;
info->shi2_path = 1 + (((unsigned char *) (info + 1)) - outp->datap);
- }
+ }
- outp->totalData = totalData;
- outp->totalParms = totalParam;
+ outp->totalData = totalData;
+ outp->totalParms = totalParam;
- smb_SendTran2Packet(vcp, outp, op);
- smb_FreeTran2Packet(outp);
+ smb_SendTran2Packet(vcp, outp, op);
+ smb_FreeTran2Packet(outp);
- return code;
+ return code;
}
typedef struct smb_rap_wksta_info_10 {
- DWORD wki10_computername; /*char *wki10_computername;*/
- DWORD wki10_username; /* char *wki10_username; */
- DWORD wki10_langroup; /* char *wki10_langroup;*/
- unsigned char wki10_ver_major;
- unsigned char wki10_ver_minor;
- DWORD wki10_logon_domain; /*char *wki10_logon_domain;*/
- DWORD wki10_oth_domains; /* char *wki10_oth_domains;*/
+ DWORD wki10_computername; /*char *wki10_computername;*/
+ DWORD wki10_username; /* char *wki10_username; */
+ DWORD wki10_langroup; /* char *wki10_langroup;*/
+ unsigned char wki10_ver_major;
+ unsigned char wki10_ver_minor;
+ DWORD wki10_logon_domain; /*char *wki10_logon_domain;*/
+ DWORD wki10_oth_domains; /* char *wki10_oth_domains;*/
} smb_rap_wksta_info_10_t;
long smb_ReceiveRAPNetWkstaGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
{
- smb_tran2Packet_t *outp;
+ smb_tran2Packet_t *outp;
long code = 0;
- int infoLevel;
- int bufsize;
- unsigned short * tp;
- int totalData;
- int totalParams;
- smb_rap_wksta_info_10_t * info;
- char * cstrp;
- smb_user_t *uidp;
-
- tp = p->parmsp + 1; /* Skip over function number */
- (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */
- (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */
- infoLevel = *tp++;
- bufsize = *tp++;
-
- if(infoLevel != 10) {
- return CM_ERROR_INVAL;
- }
+ int infoLevel;
+ int bufsize;
+ unsigned short * tp;
+ int totalData;
+ int totalParams;
+ smb_rap_wksta_info_10_t * info;
+ char * cstrp;
+ smb_user_t *uidp;
+
+ tp = p->parmsp + 1; /* Skip over function number */
+ (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */
+ (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */
+ infoLevel = *tp++;
+ bufsize = *tp++;
+
+ if (infoLevel != 10) {
+ return CM_ERROR_INVAL;
+ }
- totalParams = 6;
+ totalParams = 6;
- /* infolevel 10 */
- totalData = sizeof(*info) + /* info */
- MAX_COMPUTERNAME_LENGTH + /* wki10_computername */
- SMB_MAX_USERNAME_LENGTH + /* wki10_username */
- MAX_COMPUTERNAME_LENGTH + /* wki10_langroup */
- MAX_COMPUTERNAME_LENGTH + /* wki10_logon_domain */
- 1; /* wki10_oth_domains (null)*/
+ /* infolevel 10 */
+ totalData = sizeof(*info) + /* info */
+ MAX_COMPUTERNAME_LENGTH + /* wki10_computername */
+ SMB_MAX_USERNAME_LENGTH + /* wki10_username */
+ MAX_COMPUTERNAME_LENGTH + /* wki10_langroup */
+ MAX_COMPUTERNAME_LENGTH + /* wki10_logon_domain */
+ 1; /* wki10_oth_domains (null)*/
- outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParams, totalData);
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParams, totalData);
- memset(outp->parmsp,0,totalParams);
- memset(outp->datap,0,totalData);
+ memset(outp->parmsp,0,totalParams);
+ memset(outp->datap,0,totalData);
info = (smb_rap_wksta_info_10_t *) outp->datap;
- cstrp = (char *) (info + 1);
-
- info->wki10_computername = (DWORD) (cstrp - outp->datap);
- strcpy(cstrp, smb_localNamep);
- cstrp += strlen(cstrp) + 1;
-
- info->wki10_username = (DWORD) (cstrp - outp->datap);
- uidp = smb_FindUID(vcp, p->uid, 0);
- if(uidp) {
- lock_ObtainMutex(&uidp->mx);
- if(uidp->unp && uidp->unp->name)
- strcpy(cstrp, uidp->unp->name);
- lock_ReleaseMutex(&uidp->mx);
- smb_ReleaseUID(uidp);
- }
- cstrp += strlen(cstrp) + 1;
+ cstrp = (char *) (info + 1);
+
+ info->wki10_computername = (DWORD) (cstrp - outp->datap);
+ strcpy(cstrp, smb_localNamep);
+ cstrp += strlen(cstrp) + 1;
+
+ info->wki10_username = (DWORD) (cstrp - outp->datap);
+ uidp = smb_FindUID(vcp, p->uid, 0);
+ if (uidp) {
+ lock_ObtainMutex(&uidp->mx);
+ if(uidp->unp && uidp->unp->name)
+ strcpy(cstrp, uidp->unp->name);
+ lock_ReleaseMutex(&uidp->mx);
+ smb_ReleaseUID(uidp);
+ }
+ cstrp += strlen(cstrp) + 1;
- info->wki10_langroup = (DWORD) (cstrp - outp->datap);
- strcpy(cstrp, "WORKGROUP");
- cstrp += strlen(cstrp) + 1;
+ info->wki10_langroup = (DWORD) (cstrp - outp->datap);
+ strcpy(cstrp, "WORKGROUP");
+ cstrp += strlen(cstrp) + 1;
- /* TODO: Not sure what values these should take, but these work */
- info->wki10_ver_major = 5;
- info->wki10_ver_minor = 1;
+ /* TODO: Not sure what values these should take, but these work */
+ info->wki10_ver_major = 5;
+ info->wki10_ver_minor = 1;
- info->wki10_logon_domain = (DWORD) (cstrp - outp->datap);
- strcpy(cstrp, smb_ServerDomainName);
- cstrp += strlen(cstrp) + 1;
+ info->wki10_logon_domain = (DWORD) (cstrp - outp->datap);
+ strcpy(cstrp, smb_ServerDomainName);
+ cstrp += strlen(cstrp) + 1;
- info->wki10_oth_domains = (DWORD) (cstrp - outp->datap);
- cstrp ++; /* no other domains */
+ info->wki10_oth_domains = (DWORD) (cstrp - outp->datap);
+ cstrp ++; /* no other domains */
- outp->totalData = (unsigned short) (cstrp - outp->datap); /* actual data size */
- outp->parmsp[2] = outp->totalData;
- outp->totalParms = totalParams;
+ outp->totalData = (unsigned short) (cstrp - outp->datap); /* actual data size */
+ outp->parmsp[2] = outp->totalData;
+ outp->totalParms = totalParams;
- smb_SendTran2Packet(vcp,outp,op);
- smb_FreeTran2Packet(outp);
+ smb_SendTran2Packet(vcp,outp,op);
+ smb_FreeTran2Packet(outp);
- return code;
+ return code;
}
typedef struct smb_rap_server_info_0 {
long smb_ReceiveRAPNetServerGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
{
- smb_tran2Packet_t *outp;
+ smb_tran2Packet_t *outp;
long code = 0;
- int infoLevel;
- int bufsize;
- unsigned short * tp;
- int totalData;
- int totalParams;
+ int infoLevel;
+ int bufsize;
+ unsigned short * tp;
+ int totalData;
+ int totalParams;
smb_rap_server_info_0_t * info0;
smb_rap_server_info_1_t * info1;
char * cstrp;
- tp = p->parmsp + 1; /* Skip over function number */
- (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */
- (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */
- infoLevel = *tp++;
- bufsize = *tp++;
+ tp = p->parmsp + 1; /* Skip over function number */
+ (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */
+ (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */
+ infoLevel = *tp++;
+ bufsize = *tp++;
- if(infoLevel != 0 && infoLevel != 1) {
+ if (infoLevel != 0 && infoLevel != 1) {
return CM_ERROR_INVAL;
}
- totalParams = 6;
-
- totalData =
+ totalParams = 6;
+
+ totalData =
(infoLevel == 0) ? sizeof(smb_rap_server_info_0_t)
: (sizeof(smb_rap_server_info_1_t) + smb_ServerCommentLen);
- outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParams, totalData);
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParams, totalData);
- memset(outp->parmsp,0,totalParams);
- memset(outp->datap,0,totalData);
+ memset(outp->parmsp,0,totalParams);
+ memset(outp->datap,0,totalData);
- if(infoLevel == 0) {
+ if (infoLevel == 0) {
info0 = (smb_rap_server_info_0_t *) outp->datap;
cstrp = (char *) (info0 + 1);
strcpy(info0->sv0_name, "AFS");
- } else { /* infoLevel == 1 */
+ } else { /* infoLevel == SMB_INFO_STANDARD */
info1 = (smb_rap_server_info_1_t *) outp->datap;
cstrp = (char *) (info1 + 1);
strcpy(info1->sv1_name, "AFS");
}
totalData = cstrp - outp->datap;
- outp->totalData = min(bufsize,totalData); /* actual data size */
+ outp->totalData = min(bufsize,totalData); /* actual data size */
outp->parmsp[0] = (outp->totalData == totalData)? 0 : ERROR_MORE_DATA;
- outp->parmsp[2] = totalData;
- outp->totalParms = totalParams;
+ outp->parmsp[2] = totalData;
+ outp->totalParms = totalParams;
- smb_SendTran2Packet(vcp,outp,op);
- smb_FreeTran2Packet(outp);
+ smb_SendTran2Packet(vcp,outp,op);
+ smb_FreeTran2Packet(outp);
return code;
}
int firstPacket;
long code = 0;
- /* We sometimes see 0 word count. What to do? */
- if (*inp->wctp == 0) {
+ /* We sometimes see 0 word count. What to do? */
+ if (*inp->wctp == 0) {
#ifndef DJGPP
- HANDLE h;
- char *ptbuf[1];
+ HANDLE h;
+ char *ptbuf[1];
- osi_Log0(smb_logp, "TRANSACTION2 word count = 0");
+ osi_Log0(smb_logp, "TRANSACTION2 word count = 0");
- h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
- ptbuf[0] = "Transaction2 word count = 0";
- ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
- 1, inp->ncb_length, ptbuf, inp);
- DeregisterEventSource(h);
+ h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
+ ptbuf[0] = "Transaction2 word count = 0";
+ ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
+ 1, inp->ncb_length, ptbuf, inp);
+ DeregisterEventSource(h);
#else /* DJGPP */
- osi_Log0(smb_logp, "TRANSACTION2 word count = 0");
+ osi_Log0(smb_logp, "TRANSACTION2 word count = 0");
#endif /* !DJGPP */
smb_SetSMBDataLength(outp, 0);
smb_SendPacket(vcp, outp);
- return 0;
- }
+ return 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);
+ /* find the packet we're reassembling */
+ lock_ObtainWrite(&smb_globalLock);
asp = smb_FindTran2Packet(vcp, inp);
if (!asp) {
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;
+ if (firstPacket) {
+ parmDisp = dataDisp = 0;
parmOffset = smb_GetSMBParm(inp, 10);
dataOffset = smb_GetSMBParm(inp, 12);
parmCount = smb_GetSMBParm(inp, 9);
dataCount = smb_GetSMBParm(inp, 11);
- asp->maxReturnParms = smb_GetSMBParm(inp, 2);
+ asp->maxReturnParms = smb_GetSMBParm(inp, 2);
asp->maxReturnData = smb_GetSMBParm(inp, 3);
- osi_Log3(smb_logp, "SMB3 received T2 init packet total data %d, cur data %d, max return data %d",
+ osi_Log3(smb_logp, "SMB3 received T2 init packet total data %d, cur data %d, max return data %d",
totalData, dataCount, asp->maxReturnData);
}
else {
asp->curParms > 0 &&
asp->totalData <= asp->curData &&
asp->totalParms <= asp->curParms) {
- /* we've received it all */
+ /* we've received it all */
lock_ObtainWrite(&smb_globalLock);
- osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
+ osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
lock_ReleaseWrite(&smb_globalLock);
/* now dispatch it */
code = CM_ERROR_BADOP;
}
- /* if an error is returned, we're supposed to send an error packet,
+ /* if an error is returned, we're supposed to send an error packet,
* otherwise the dispatched function already did the data sending.
* We give dispatched proc the responsibility since it knows how much
* space to allocate.
smb_SendTran2Error(vcp, asp, outp, code);
}
- /* free the input tran 2 packet */
- lock_ObtainWrite(&smb_globalLock);
+ /* free the input tran 2 packet */
+ lock_ObtainWrite(&smb_globalLock);
smb_FreeTran2Packet(asp);
- lock_ReleaseWrite(&smb_globalLock);
+ lock_ReleaseWrite(&smb_globalLock);
}
else if (firstPacket) {
- /* the first packet in a multi-packet request, we need to send an
+ /* the first packet in a multi-packet request, we need to send an
* ack to get more data.
*/
smb_SetSMBDataLength(outp, 0);
smb_SendPacket(vcp, outp);
}
- return 0;
+ return 0;
}
long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
smb_fid_t *fidp;
int attributes;
char *lastNamep;
- time_t dosTime;
+ afs_uint32 dosTime;
int openFun;
int trunc;
int openMode;
/* compute initial mode bits based on read-only flag in attributes */
initialModeBits = 0666;
- if (attributes & 1) initialModeBits &= ~0222;
+ if (attributes & 1)
+ initialModeBits &= ~0222;
pathp = (char *) (&p->parmsp[14]);
-
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
+
outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0);
spacep = cm_GetSpace();
/* copy out remainder of the parms */
parmSlot = 0;
- outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
+ outp->parmsp[parmSlot++] = fidp->fid;
if (extraInfo) {
- outp->parmsp[parmSlot] = /* attrs */ 0; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++; /* mod time */
- outp->parmsp[parmSlot] = 0; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++; /* len */
- outp->parmsp[parmSlot] = 0x7fff; parmSlot++;
- outp->parmsp[parmSlot] = openMode; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */
- outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */
+ outp->parmsp[parmSlot++] = 0; /* attrs */
+ outp->parmsp[parmSlot++] = 0; /* mod time */
+ outp->parmsp[parmSlot++] = 0;
+ outp->parmsp[parmSlot++] = 0; /* len */
+ outp->parmsp[parmSlot++] = 0x7fff;
+ outp->parmsp[parmSlot++] = openMode;
+ outp->parmsp[parmSlot++] = 0; /* file type 0 ==> normal file or dir */
+ outp->parmsp[parmSlot++] = 0; /* IPC junk */
}
/* and the final "always present" stuff */
- outp->parmsp[parmSlot] = /* openAction found existing file */ 1; parmSlot++;
+ outp->parmsp[parmSlot++] = 1; /* openAction found existing file */
/* next write out the "unique" ID */
- outp->parmsp[parmSlot] = 0x1234; parmSlot++;
- outp->parmsp[parmSlot] = 0x5678; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++;
+ outp->parmsp[parmSlot++] = 0x1234;
+ outp->parmsp[parmSlot++] = 0x5678;
+ outp->parmsp[parmSlot++] = 0;
if (returnEALength) {
- outp->parmsp[parmSlot] = 0; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++;
+ outp->parmsp[parmSlot++] = 0;
+ outp->parmsp[parmSlot++] = 0;
}
outp->totalData = 0;
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if (code == CM_ERROR_TIDIPC) {
- /* Attempt to use TID allocated for IPC. The client is
- probably trying to locate DCE RPC end points, which
- we don't support. */
+ /* Attempt to use a TID allocated for IPC. The client
+ * is probably looking for DCE RPC end points which we
+ * don't support OR it could be looking to make a DFS
+ * referral request.
+ */
osi_Log0(smb_logp, "Tran2Open received IPC TID");
+#ifndef DFS_SUPPORT
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
return CM_ERROR_NOSUCHPATH;
+#endif
}
dscp = NULL;
- code = cm_NameI(cm_rootSCachep, pathp,
+ code = cm_NameI(cm_data.rootSCachep, pathp,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
if (code != 0) {
- code = cm_NameI(cm_rootSCachep, spacep->data,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
cm_FreeSpace(spacep);
return code;
}
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ smb_FreeTran2Packet(outp);
+ if ( WANTS_DFS_PATHNAMES(p) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* otherwise, scp points to the parent directory. Do a lookup,
* and truncate the file if we find it, otherwise we create the
* file.
smb_FreeTran2Packet(outp);
return code;
}
- }
- else {
- 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.
+ } else {
+#ifdef DFS_SUPPORT
+ if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ smb_FreeTran2Packet(outp);
+ if ( WANTS_DFS_PATHNAMES(p) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
+ /* macintosh is expensive to program for it */
+ cm_FreeSpace(spacep);
+ }
+
+ /* if 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) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
if (excl) {
/* oops, file shouldn't be there */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
else
openAction = 1; /* found existing file */
}
- else if (!(openFun & SMB_ATTR_DIRECTORY)) {
+ else if (!(openFun & 0x10)) {
/* don't create if not found */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
osi_assert(scp == NULL);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
}
/* we don't need this any longer */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
if (code) {
/* something went wrong creating or truncating the file */
- if (scp) cm_ReleaseSCache(scp);
+ if (scp)
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
return code;
code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
if (code == 0) {
/* we have a more accurate file to use (the
- * target of the symbolic link). Otherwise,
- * we'll just use the symlink anyway.
- */
+ * target of the symbolic link). Otherwise,
+ * we'll just use the symlink anyway.
+ */
osi_Log2(smb_logp, "symlink vp %x to vp %x",
scp, targetScp);
cm_ReleaseSCache(scp);
/* copy out remainder of the parms */
parmSlot = 0;
- outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
+ outp->parmsp[parmSlot++] = fidp->fid;
lock_ObtainMutex(&scp->mx);
if (extraInfo) {
- outp->parmsp[parmSlot] = smb_Attributes(scp); parmSlot++;
+ outp->parmsp[parmSlot++] = smb_Attributes(scp);
smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
- outp->parmsp[parmSlot] = (unsigned short)(dosTime & 0xffff); parmSlot++;
- outp->parmsp[parmSlot] = (unsigned short)((dosTime>>16) & 0xffff); parmSlot++;
- outp->parmsp[parmSlot] = (unsigned short) (scp->length.LowPart & 0xffff);
- parmSlot++;
- outp->parmsp[parmSlot] = (unsigned short) ((scp->length.LowPart >> 16) & 0xffff);
- parmSlot++;
- outp->parmsp[parmSlot] = openMode; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */
- outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */
+ outp->parmsp[parmSlot++] = (unsigned short)(dosTime & 0xffff);
+ outp->parmsp[parmSlot++] = (unsigned short)((dosTime>>16) & 0xffff);
+ outp->parmsp[parmSlot++] = (unsigned short) (scp->length.LowPart & 0xffff);
+ outp->parmsp[parmSlot++] = (unsigned short) ((scp->length.LowPart >> 16) & 0xffff);
+ outp->parmsp[parmSlot++] = openMode;
+ outp->parmsp[parmSlot++] = 0; /* file type 0 ==> normal file or dir */
+ outp->parmsp[parmSlot++] = 0; /* IPC junk */
}
/* and the final "always present" stuff */
- outp->parmsp[parmSlot] = openAction; parmSlot++;
+ outp->parmsp[parmSlot++] = openAction;
/* next write out the "unique" ID */
- outp->parmsp[parmSlot] = (unsigned short) (scp->fid.vnode & 0xffff); parmSlot++;
- outp->parmsp[parmSlot] = (unsigned short) (scp->fid.volume & 0xffff); parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++;
+ outp->parmsp[parmSlot++] = (unsigned short) (scp->fid.vnode & 0xffff);
+ outp->parmsp[parmSlot++] = (unsigned short) (scp->fid.volume & 0xffff);
+ outp->parmsp[parmSlot++] = 0;
if (returnEALength) {
- outp->parmsp[parmSlot] = 0; parmSlot++;
- outp->parmsp[parmSlot] = 0; parmSlot++;
+ outp->parmsp[parmSlot++] = 0;
+ outp->parmsp[parmSlot++] = 0;
}
lock_ReleaseMutex(&scp->mx);
outp->totalData = 0; /* total # of data bytes */
case 0x103: responseSize = sizeof(qi.u.FSsizeInfo); break;
case 0x104: responseSize = sizeof(qi.u.FSdeviceInfo); break;
case 0x105: responseSize = sizeof(qi.u.FSattributeInfo); break;
+ case 0x200: /* CIFS Unix Info */
+ case 0x301: /* Mac FS Info */
default: return CM_ERROR_INVAL;
}
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, userp, tidPathp,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold, userp, tidPathp,
reqp, &dscp);
cm_FreeSpace(spacep);
- if (code) return code;
+ if (code)
+ return code;
+
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ return CM_ERROR_PATH_NOT_COVERED;
+ }
+#endif /* DFS_SUPPORT */
if (!lastNamep) lastNamep = pathp;
else lastNamep++;
rock.shortName = shortName;
rock.vnode = vnode;
rock.maskp = lastNamep;
- code = cm_ApplyDir(dscp, cm_GetShortNameProc, &rock, &thyper, userp,
- reqp, NULL);
+ code = cm_ApplyDir(dscp, cm_GetShortNameProc, &rock, &thyper, userp, reqp, NULL);
cm_ReleaseSCache(dscp);
long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx)
{
smb_tran2Packet_t *outp;
- time_t dosTime;
+ afs_uint32 dosTime;
FILETIME ft;
unsigned short infoLevel;
int nbytesRequired;
cm_InitReq(&req);
infoLevel = p->parmsp[0];
- if (infoLevel == 6) nbytesRequired = 0;
- else if (infoLevel == 1) nbytesRequired = 22;
- else if (infoLevel == 2) nbytesRequired = 26;
- else if (infoLevel == 0x101) nbytesRequired = 40;
- else if (infoLevel == 0x102) nbytesRequired = 24;
- else if (infoLevel == 0x103) nbytesRequired = 4;
- else if (infoLevel == 0x108) nbytesRequired = 30;
+ if (infoLevel == SMB_INFO_IS_NAME_VALID)
+ nbytesRequired = 0;
+ else if (infoLevel == SMB_INFO_STANDARD)
+ nbytesRequired = 22;
+ else if (infoLevel == SMB_INFO_QUERY_EA_SIZE)
+ nbytesRequired = 26;
+ else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO)
+ nbytesRequired = 40;
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO)
+ nbytesRequired = 24;
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+ nbytesRequired = 4;
+ else if (infoLevel == SMB_QUERY_FILE_ALT_NAME_INFO)
+ nbytesRequired = 30;
else {
osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
* 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.
*/
- if (infoLevel == 6) {
+ if (infoLevel == SMB_INFO_IS_NAME_VALID) {
smb_SendTran2Packet(vcp, outp, opx);
smb_FreeTran2Packet(outp);
return 0;
* yet been evaluated and for directories that haven't yet been
* fetched.
*/
- if (infoLevel == 0x101) {
+ if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->data, &lastComp,
(char *)(&p->parmsp[3]));
+#ifndef SPECIAL_FOLDERS
/* Make sure that lastComp is not NULL */
if (lastComp) {
- if (strcmp(lastComp, "\\desktop.ini") == 0) {
- code = cm_NameI(cm_rootSCachep, spacep->data,
+ if (stricmp(lastComp, "\\desktop.ini") == 0) {
+ code = cm_NameI(cm_data.rootSCachep, spacep->data,
CM_FLAG_CASEFOLD
| CM_FLAG_DIRSEARCH
| CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
if (code == 0) {
- if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT
- && !dscp->mountRootFidp)
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ if ( WANTS_DFS_PATHNAMES(p) )
+ code = CM_ERROR_PATH_NOT_COVERED;
+ else
+ code = CM_ERROR_BADSHARENAME;
+ } else
+#endif /* DFS_SUPPORT */
+ if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
code = CM_ERROR_NOSUCHFILE;
else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
cm_buf_t *bp = buf_Find(dscp, &hzero);
}
}
}
+#endif /* SPECIAL_FOLDERS */
+
cm_FreeSpace(spacep);
}
/* now do namei and stat, and copy out the info */
- code = cm_NameI(cm_rootSCachep, (char *)(&p->parmsp[3]),
+ code = cm_NameI(cm_data.rootSCachep, (char *)(&p->parmsp[3]),
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
if (code) {
return 0;
}
+#ifdef DFS_SUPPORT
+ if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(p) )
+ code = CM_ERROR_PATH_NOT_COVERED;
+ else
+ code = CM_ERROR_BADSHARENAME;
+ smb_SendTran2Error(vcp, p, opx, code);
+ smb_FreeTran2Packet(outp);
+ return 0;
+ }
+#endif /* DFS_SUPPORT */
+
lock_ObtainMutex(&scp->mx);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
goto done;
}
- if (infoLevel == 1 || infoLevel == 2) {
+ if (infoLevel == SMB_INFO_STANDARD || infoLevel == SMB_INFO_QUERY_EA_SIZE) {
smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
*((u_long *)op) = dosTime; op += 4; /* creation time */
*((u_long *)op) = dosTime; op += 4; /* access time */
attributes = smb_Attributes(scp);
*((u_short *)op) = attributes; op += 2; /* attributes */
}
- else if (infoLevel == 0x101) {
+ else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
*((FILETIME *)op) = ft; op += 8; /* creation time */
*((FILETIME *)op) = ft; op += 8; /* last access time */
*((u_long *)op) = extAttributes; op += 4; /* extended attribs */
*((u_long *)op) = 0; op += 4; /* don't know what this is */
}
- else if (infoLevel == 0x102) {
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
*((LARGE_INTEGER *)op) = scp->length; op += 8; /* alloc size */
*((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */
*((u_long *)op) = scp->linkCount; op += 4;
*op++ = (scp->fileType == CM_SCACHETYPE_DIRECTORY ? 1 : 0);
*op++ = 0;
}
- else if (infoLevel == 0x103) {
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO) {
memset(op, 0, 4); op += 4; /* EA size */
}
/* now, if we are being asked about extended attrs, return a 0 size */
- if (infoLevel == 2) {
+ if (infoLevel == SMB_INFO_QUERY_EA_SIZE) {
*((u_long *)op) = 0; op += 4;
}
}
infoLevel = p->parmsp[1];
- if (infoLevel == 0x101) nbytesRequired = 40;
- else if (infoLevel == 0x102) nbytesRequired = 24;
- else if (infoLevel == 0x103) nbytesRequired = 4;
- else if (infoLevel == 0x104) nbytesRequired = 6;
+ if (infoLevel == SMB_QUERY_FILE_BASIC_INFO)
+ nbytesRequired = 40;
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO)
+ nbytesRequired = 24;
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+ nbytesRequired = 4;
+ else if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
+ nbytesRequired = 6;
else {
osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
* Marshall the output data.
*/
op = outp->datap;
- if (infoLevel == 0x101) {
+ if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
*((FILETIME *)op) = ft; op += 8; /* creation time */
*((FILETIME *)op) = ft; op += 8; /* last access time */
*((u_long *)op) = attributes; op += 4;
*((u_long *)op) = 0; op += 4;
}
- else if (infoLevel == 0x102) {
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
*((LARGE_INTEGER *)op) = scp->length; op += 8; /* alloc size */
*((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */
*((u_long *)op) = scp->linkCount; op += 4;
*op++ = 0;
*op++ = 0;
}
- else if (infoLevel == 0x103) {
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO) {
*((u_long *)op) = 0; op += 4;
}
- else if (infoLevel == 0x104) {
+ else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
unsigned long len;
char *name;
return 0;
}
- if (infoLevel == 0x102 && !(fidp->flags & SMB_FID_OPENDELETE)) {
+ if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO && !(fidp->flags & SMB_FID_OPENDELETE)) {
smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
smb_ReleaseFID(fidp);
return 0;
}
- if ((infoLevel == 0x103 || infoLevel == 0x104)
+ if ((infoLevel == SMB_QUERY_FILE_EA_INFO || infoLevel == SMB_QUERY_FILE_NAME_INFO)
&& !(fidp->flags & SMB_FID_OPENWRITE)) {
smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
smb_ReleaseFID(fidp);
scp = fidp->scp;
- if (infoLevel == 0x101) {
+ if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
FILETIME lastMod;
unsigned int attribute;
cm_attr_t attr;
if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) &&
lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
- smb_UnixTimeFromLargeSearchTime(&attr.clientModTime,
- &lastMod);
+ smb_UnixTimeFromLargeSearchTime(&attr.clientModTime, &lastMod);
fidp->flags |= SMB_FID_MTIMESETDONE;
}
else
code = 0;
}
- else if (infoLevel == 0x103 || infoLevel == 0x104) {
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO || infoLevel == SMB_QUERY_FILE_NAME_INFO) {
LARGE_INTEGER size = *((LARGE_INTEGER *)(p->datap));
cm_attr_t attr;
attr.length.HighPart = size.HighPart;
code = cm_SetAttr(scp, &attr, userp, &req);
}
- else if (infoLevel == 0x102) {
+ else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
if (*((char *)(p->datap))) {
code = cm_CheckNTDelete(fidp->NTopen_dscp, scp, userp,
&req);
return CM_ERROR_BADOP;
}
+struct smb_v2_referral {
+ USHORT ServerType;
+ USHORT ReferralFlags;
+ ULONG Proximity;
+ ULONG TimeToLive;
+ USHORT DfsPathOffset;
+ USHORT DfsAlternativePathOffset;
+ USHORT NetworkAddressOffset;
+};
+
long
-smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
+smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
{
- osi_Log0(smb_logp,"ReceiveTran2GetDFSReferral - NOT_SUPPORTED");
+ /* This is a UNICODE only request (bit15 of Flags2) */
+ /* The TID must be IPC$ */
+
+ /* The documentation for the Flags response field is contradictory */
+
+ /* Use Version 1 Referral Element Format */
+ /* ServerType = 0; indicates the next server should be queried for the file */
+ /* ReferralFlags = 0x01; PathConsumed characters should be stripped */
+ /* Node = UnicodeString of UNC path of the next share name */
+#ifdef DFS_SUPPORT
+ long code = 0;
+ int maxReferralLevel = 0;
+ char requestFileName[1024] = "";
+ smb_tran2Packet_t *outp = 0;
+ cm_user_t *userp = 0;
+ cm_req_t req;
+ CPINFO CodePageInfo;
+ int i, nbnLen, reqLen;
+ int idx;
+
+ cm_InitReq(&req);
+
+ maxReferralLevel = p->parmsp[0];
+
+ GetCPInfo(CP_ACP, &CodePageInfo);
+ WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) &p->parmsp[1], -1,
+ requestFileName, 1024, NULL, NULL);
+
+ osi_Log2(smb_logp,"ReceiveTran2GetDfsReferral [%d][%s]",
+ maxReferralLevel, osi_LogSaveString(smb_logp, requestFileName));
+
+ nbnLen = strlen(cm_NetbiosName);
+ reqLen = strlen(requestFileName);
+
+ if (reqLen == nbnLen + 5 &&
+ requestFileName[0] == '\\' &&
+ !_strnicmp(cm_NetbiosName,&requestFileName[1],nbnLen) &&
+ requestFileName[nbnLen+1] == '\\' &&
+ !_strnicmp("all",&requestFileName[nbnLen+2],3))
+ {
+ USHORT * sp;
+ struct smb_v2_referral * v2ref;
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 2 * (reqLen + 8));
+
+ sp = (USHORT *)outp->datap;
+ idx = 0;
+ sp[idx++] = reqLen; /* path consumed */
+ sp[idx++] = 1; /* number of referrals */
+ sp[idx++] = 0x03; /* flags */
+#ifdef DFS_VERSION_1
+ sp[idx++] = 1; /* Version Number */
+ sp[idx++] = reqLen + 4; /* Referral Size */
+ sp[idx++] = 1; /* Type = SMB Server */
+ sp[idx++] = 0; /* Do not strip path consumed */
+ for ( i=0;i<=reqLen; i++ )
+ sp[i+idx] = requestFileName[i];
+#else /* DFS_VERSION_2 */
+ sp[idx++] = 2; /* Version Number */
+ sp[idx++] = sizeof(struct smb_v2_referral); /* Referral Size */
+ idx += (sizeof(struct smb_v2_referral) / 2);
+ v2ref = (struct smb_v2_referral *) &sp[5];
+ v2ref->ServerType = 1; /* SMB Server */
+ v2ref->ReferralFlags = 0x03;
+ v2ref->Proximity = 0; /* closest */
+ v2ref->TimeToLive = 3600; /* seconds */
+ v2ref->DfsPathOffset = idx * 2;
+ v2ref->DfsAlternativePathOffset = idx * 2;
+ v2ref->NetworkAddressOffset = 0;
+ for ( i=0;i<=reqLen; i++ )
+ sp[i+idx] = requestFileName[i];
+#endif
+ } else {
+ userp = smb_GetTran2User(vcp, p);
+ if (!userp) {
+ osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
+ code = CM_ERROR_BADSMB;
+ goto done;
+ }
+
+ /* not done yet */
+ code = CM_ERROR_NOSUCHPATH;
+ }
+
+ done:
+ if (userp)
+ cm_ReleaseUser(userp);
+ if (code == 0)
+ smb_SendTran2Packet(vcp, outp, op);
+ else
+ smb_SendTran2Error(vcp, p, op, code);
+ if (outp)
+ smb_FreeTran2Packet(outp);
+
+ return 0;
+#else /* DFS_SUPPORT */
+ osi_Log0(smb_logp,"ReceiveTran2GetDfsReferral - NOT_SUPPORTED");
return CM_ERROR_BADOP;
+#endif /* DFS_SUPPORT */
}
long
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
+ * somewhere. Even then I don't think there is anything for us to do.
+ * So let's return an error value.
+ */
+
osi_Log0(smb_logp,"ReceiveTran2ReportDFSInconsistency - NOT_SUPPORTED");
return CM_ERROR_BADOP;
}
cm_scache_t *scp;
cm_scache_t *targetScp; /* target if scp is a symlink */
char *dptr;
- time_t dosTime;
+ afs_uint32 dosTime;
FILETIME ft;
int shortTemp;
unsigned short attr;
lock_ObtainMutex(&scp->mx);
code = cm_SyncOp(scp, NULL, userp, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code) {
- lock_ReleaseMutex(&scp->mx);
- cm_ReleaseSCache(scp);
+ if (code) {
+ lock_ReleaseMutex(&scp->mx);
+ cm_ReleaseSCache(scp);
dptr = patchp->dptr;
ft.dwHighDateTime = 0x19DB200;
ft.dwLowDateTime = 0x5BB78980;
- /* copy to Creation Time */
- *((FILETIME *)dptr) = ft;
- dptr += 8;
+ /* copy to Creation Time */
+ *((FILETIME *)dptr) = ft;
+ dptr += 8;
- /* copy to Last Access Time */
- *((FILETIME *)dptr) = ft;
- dptr += 8;
+ /* copy to Last Access Time */
+ *((FILETIME *)dptr) = ft;
+ dptr += 8;
- /* copy to Last Write Time */
- *((FILETIME *)dptr) = ft;
- dptr += 8;
+ /* copy to Last Write Time */
+ *((FILETIME *)dptr) = ft;
+ dptr += 8;
- /* copy to Change Time */
- *((FILETIME *)dptr) = ft;
+ /* copy to Change Time */
+ *((FILETIME *)dptr) = ft;
dptr += 24;
/* merge in hidden attribute */
if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
- *((u_long *)dptr) = SMB_ATTR_HIDDEN;
+ *((u_long *)dptr) = SMB_ATTR_HIDDEN;
}
- dptr += 4;
+ dptr += 4;
} else {
/* 1969-12-31 23:59:58 +00*/
dosTime = 0xEBBFBF7D;
- /* and copy out date */
- shortTemp = (dosTime>>16) & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
+ /* and copy out date */
+ shortTemp = (dosTime>>16) & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
- /* copy out creation time */
- shortTemp = dosTime & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
+ /* copy out creation time */
+ shortTemp = dosTime & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
- /* and copy out date */
- shortTemp = (dosTime>>16) & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
+ /* and copy out date */
+ shortTemp = (dosTime>>16) & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
- /* copy out access time */
- shortTemp = dosTime & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
-
- /* and copy out date */
- shortTemp = (dosTime>>16) & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
+ /* copy out access time */
+ shortTemp = dosTime & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* and copy out date */
+ shortTemp = (dosTime>>16) & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
- /* copy out mod time */
- shortTemp = dosTime & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 10;
+ /* copy out mod time */
+ shortTemp = dosTime & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 10;
/* merge in hidden (dot file) attribute */
if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
attr = SMB_ATTR_HIDDEN;
- *dptr++ = attr & 0xff;
- *dptr++ = (attr >> 8) & 0xff;
- }
+ *dptr++ = attr & 0xff;
+ *dptr++ = (attr >> 8) & 0xff;
+ }
}
- continue;
+ continue;
}
/* now watch for a symlink */
lock_ObtainMutex(&scp->mx);
}
- dptr = patchp->dptr;
+ dptr = patchp->dptr;
- if (infoLevel >= 0x101) {
- /* get filetime */
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ if (infoLevel >= 0x101) {
+ /* get filetime */
+ smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
- /* copy to Creation Time */
- *((FILETIME *)dptr) = ft;
- dptr += 8;
+ /* copy to Creation Time */
+ *((FILETIME *)dptr) = ft;
+ dptr += 8;
- /* copy to Last Access Time */
- *((FILETIME *)dptr) = ft;
- dptr += 8;
+ /* copy to Last Access Time */
+ *((FILETIME *)dptr) = ft;
+ dptr += 8;
- /* copy to Last Write Time */
- *((FILETIME *)dptr) = ft;
- dptr += 8;
+ /* copy to Last Write Time */
+ *((FILETIME *)dptr) = ft;
+ dptr += 8;
- /* copy to Change Time */
- *((FILETIME *)dptr) = ft;
- dptr += 8;
+ /* copy to Change Time */
+ *((FILETIME *)dptr) = ft;
+ dptr += 8;
- /* Use length for both file length and alloc length */
- *((LARGE_INTEGER *)dptr) = scp->length;
- dptr += 8;
- *((LARGE_INTEGER *)dptr) = scp->length;
- dptr += 8;
+ /* Use length for both file length and alloc length */
+ *((LARGE_INTEGER *)dptr) = scp->length;
+ dptr += 8;
+ *((LARGE_INTEGER *)dptr) = scp->length;
+ dptr += 8;
- /* Copy attributes */
- lattr = smb_ExtAttributes(scp);
+ /* Copy attributes */
+ lattr = smb_ExtAttributes(scp);
+ if (code == CM_ERROR_NOSUCHPATH && scp->fileType == CM_SCACHETYPE_SYMLINK) {
+ if (lattr == SMB_ATTR_NORMAL)
+ lattr = SMB_ATTR_DIRECTORY;
+ else
+ lattr |= SMB_ATTR_DIRECTORY;
+ }
/* merge in hidden (dot file) attribute */
- if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
- lattr |= SMB_ATTR_HIDDEN;
- *((u_long *)dptr) = lattr;
- dptr += 4;
- }
- else {
- /* get dos time */
- smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
-
- /* and copy out date */
- shortTemp = (dosTime>>16) & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
-
- /* copy out creation time */
- shortTemp = dosTime & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
-
- /* and copy out date */
- shortTemp = (dosTime>>16) & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
-
- /* copy out access time */
- shortTemp = dosTime & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
-
- /* and copy out date */
- shortTemp = (dosTime>>16) & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
-
- /* copy out mod time */
- shortTemp = dosTime & 0xffff;
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
-
- /* copy out file length and alloc length,
- * using the same for both
- */
- *((u_long *)dptr) = scp->length.LowPart;
- dptr += 4;
- *((u_long *)dptr) = scp->length.LowPart;
- dptr += 4;
-
- /* finally copy out attributes as short */
- attr = smb_Attributes(scp);
+ if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
+ if (lattr == SMB_ATTR_NORMAL)
+ lattr = SMB_ATTR_HIDDEN;
+ else
+ lattr |= SMB_ATTR_HIDDEN;
+ }
+ *((u_long *)dptr) = lattr;
+ dptr += 4;
+ } else {
+ /* get dos time */
+ smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+
+ /* and copy out date */
+ shortTemp = (dosTime>>16) & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* copy out creation time */
+ shortTemp = dosTime & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* and copy out date */
+ shortTemp = (dosTime>>16) & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* copy out access time */
+ shortTemp = dosTime & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* and copy out date */
+ shortTemp = (dosTime>>16) & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* copy out mod time */
+ shortTemp = dosTime & 0xffff;
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* copy out file length and alloc length,
+ * using the same for both
+ */
+ *((u_long *)dptr) = scp->length.LowPart;
+ dptr += 4;
+ *((u_long *)dptr) = scp->length.LowPart;
+ dptr += 4;
+
+ /* finally copy out attributes as short */
+ attr = smb_Attributes(scp);
/* merge in hidden (dot file) attribute */
- if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
- attr |= SMB_ATTR_HIDDEN;
- *dptr++ = attr & 0xff;
- *dptr++ = (attr >> 8) & 0xff;
- }
+ if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
+ if (lattr == SMB_ATTR_NORMAL)
+ lattr = SMB_ATTR_HIDDEN;
+ else
+ lattr |= SMB_ATTR_HIDDEN;
+ }
+ *dptr++ = attr & 0xff;
+ *dptr++ = (attr >> 8) & 0xff;
+ }
lock_ReleaseMutex(&scp->mx);
cm_ReleaseSCache(scp);
- }
+ }
/* now free the patches */
- for(patchp = *dirPatchespp; patchp; patchp = npatchp) {
- npatchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q);
+ for (patchp = *dirPatchespp; patchp; patchp = npatchp) {
+ npatchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q);
free(patchp);
- }
+ }
/* and mark the list as empty */
*dirPatchespp = NULL;
// BOOL : TRUE/FALSE (match/mistmatch)
BOOL
-szWildCardMatchFileName(PSZ pattern, PSZ name)
+szWildCardMatchFileName(PSZ pattern, PSZ name, int casefold)
{
PSZ pename; // points to the last 'name' character
PSZ p;
if (*pattern == '\0')
return TRUE;
for (p = pename; p >= name; --p) {
- if ((mapCaseTable[*p] == mapCaseTable[*pattern]) &&
- szWildCardMatchFileName(pattern + 1, p + 1))
+ if ((casefold && (mapCaseTable[*p] == mapCaseTable[*pattern]) ||
+ !casefold && (*p == *pattern)) &&
+ szWildCardMatchFileName(pattern + 1, p + 1, casefold))
return TRUE;
} /* endfor */
return FALSE;
default:
- if (mapCaseTable[*name] != mapCaseTable[*pattern])
+ if ((casefold && mapCaseTable[*name] != mapCaseTable[*pattern]) ||
+ (!casefold && *name != *pattern))
return FALSE;
++pattern, ++name;
break;
- } /* endswitch */
- } /* endwhile */
+ } /* endswitch */
+ } /* endwhile */
if (*pattern == '\0' || *pattern == '*' && *(pattern+1) == '\0')
return TRUE;
int smb_V3MatchMask(char *namep, char *maskp, int flags)
{
char * newmask;
- int i, j, star, qmark, retval;
+ int i, j, star, qmark, casefold, retval;
/* make sure we only match 8.3 names, if requested */
if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep))
return 0;
+ casefold = (flags & CM_FLAG_CASEFOLD) ? 1 : 0;
+
/* optimize the pattern:
* if there is a mixture of '?' and '*',
* for example the sequence "*?*?*?*"
}
newmask[j++] = '\0';
- retval = szWildCardMatchFileName(newmask, namep) ? 1:0;
+ retval = szWildCardMatchFileName(newmask, namep, casefold) ? 1:0;
free(newmask);
return retval;
*/
int smb_V3MatchMask(char *namep, char *maskp, int flags)
{
- unsigned char tcp1, tcp2; /* Pattern characters */
+ unsigned char tcp1, tcp2; /* Pattern characters */
unsigned char tcn1; /* Name characters */
- int sawDot = 0, sawStar = 0, req8dot3 = 0;
- char *starNamep, *starMaskp;
- static char nullCharp[] = {0};
+ int sawDot = 0, sawStar = 0, req8dot3 = 0;
+ char *starNamep, *starMaskp;
+ static char nullCharp[] = {0};
int casefold = flags & CM_FLAG_CASEFOLD;
- /* make sure we only match 8.3 names, if requested */
+ /* make sure we only match 8.3 names, if requested */
req8dot3 = (flags & CM_FLAG_8DOT3);
- if (req8dot3 && !cm_Is8Dot3(namep))
+ if (req8dot3 && !cm_Is8Dot3(namep))
return 0;
- /* loop */
- while (1) {
- /* Next pattern character */
- tcp1 = *maskp++;
-
- /* Next name character */
- tcn1 = *namep;
-
- if (tcp1 == 0) {
- /* 0 - end of pattern */
- if (tcn1 == 0)
- return 1;
- else
- return 0;
- }
- else if (tcp1 == '.' || tcp1 == '"') {
- if (sawDot) {
- if (tcn1 == '.') {
- namep++;
- continue;
- } else
- return 0;
- }
- else {
- /*
- * first dot in pattern;
- * must match dot or end of name
- */
- sawDot = 1;
- if (tcn1 == 0)
- continue;
- else if (tcn1 == '.') {
- sawStar = 0;
- namep++;
- continue;
- }
- else
- return 0;
- }
- }
- else if (tcp1 == '?') {
- if (tcn1 == 0 || tcn1 == '.')
- return 0;
- namep++;
- continue;
- }
- else if (tcp1 == '>') {
- if (tcn1 != 0 && tcn1 != '.')
- namep++;
- continue;
- }
- else if (tcp1 == '*' || tcp1 == '<') {
- tcp2 = *maskp++;
- if (tcp2 == 0)
- return 1;
- else if ((req8dot3 && tcp2 == '.') || tcp2 == '"') {
- while (req8dot3 && tcn1 != '.' && tcn1 != 0)
- tcn1 = *++namep;
- if (tcn1 == 0) {
- if (sawDot)
- return 0;
- else
- continue;
- }
- else {
- namep++;
- continue;
- }
- }
- else {
- /*
- * pattern character after '*' is not null or
- * period. If it is '?' or '>', we are not
- * going to understand it. If it is '*' or
- * '<', we are going to skip over it. None of
- * these are likely, I hope.
- */
- /* skip over '*' and '<' */
- while (tcp2 == '*' || tcp2 == '<')
- tcp2 = *maskp++;
-
- /* skip over characters that don't match tcp2 */
- while (req8dot3 && tcn1 != '.' && tcn1 != 0 &&
- ((casefold && cm_foldUpper[tcn1] != cm_foldUpper[tcp2]) ||
- (!casefold && tcn1 != tcp2)))
- tcn1 = *++namep;
-
- /* No match */
- if ((req8dot3 && tcn1 == '.') || tcn1 == 0)
- return 0;
-
- /* Remember where we are */
- sawStar = 1;
- starMaskp = maskp;
- starNamep = namep;
-
- namep++;
- continue;
- }
- }
- else {
- /* tcp1 is not a wildcard */
+ /* loop */
+ while (1) {
+ /* Next pattern character */
+ tcp1 = *maskp++;
+
+ /* Next name character */
+ tcn1 = *namep;
+
+ if (tcp1 == 0) {
+ /* 0 - end of pattern */
+ if (tcn1 == 0)
+ return 1;
+ else
+ return 0;
+ }
+ else if (tcp1 == '.' || tcp1 == '"') {
+ if (sawDot) {
+ if (tcn1 == '.') {
+ namep++;
+ continue;
+ } else
+ return 0;
+ }
+ else {
+ /*
+ * first dot in pattern;
+ * must match dot or end of name
+ */
+ sawDot = 1;
+ if (tcn1 == 0)
+ continue;
+ else if (tcn1 == '.') {
+ sawStar = 0;
+ namep++;
+ continue;
+ }
+ else
+ return 0;
+ }
+ }
+ else if (tcp1 == '?') {
+ if (tcn1 == 0 || tcn1 == '.')
+ return 0;
+ namep++;
+ continue;
+ }
+ else if (tcp1 == '>') {
+ if (tcn1 != 0 && tcn1 != '.')
+ namep++;
+ continue;
+ }
+ else if (tcp1 == '*' || tcp1 == '<') {
+ tcp2 = *maskp++;
+ if (tcp2 == 0)
+ return 1;
+ else if ((req8dot3 && tcp2 == '.') || tcp2 == '"') {
+ while (req8dot3 && tcn1 != '.' && tcn1 != 0)
+ tcn1 = *++namep;
+ if (tcn1 == 0) {
+ if (sawDot)
+ return 0;
+ else
+ continue;
+ }
+ else {
+ namep++;
+ continue;
+ }
+ }
+ else {
+ /*
+ * pattern character after '*' is not null or
+ * period. If it is '?' or '>', we are not
+ * going to understand it. If it is '*' or
+ * '<', we are going to skip over it. None of
+ * these are likely, I hope.
+ */
+ /* skip over '*' and '<' */
+ while (tcp2 == '*' || tcp2 == '<')
+ tcp2 = *maskp++;
+
+ /* skip over characters that don't match tcp2 */
+ while (req8dot3 && tcn1 != '.' && tcn1 != 0 &&
+ ((casefold && cm_foldUpper[tcn1] != cm_foldUpper[tcp2]) ||
+ (!casefold && tcn1 != tcp2)))
+ tcn1 = *++namep;
+
+ /* No match */
+ if ((req8dot3 && tcn1 == '.') || tcn1 == 0)
+ return 0;
+
+ /* Remember where we are */
+ sawStar = 1;
+ starMaskp = maskp;
+ starNamep = namep;
+
+ namep++;
+ continue;
+ }
+ }
+ else {
+ /* tcp1 is not a wildcard */
if ((casefold && cm_foldUpper[tcn1] == cm_foldUpper[tcp1]) ||
- (!casefold && tcn1 == tcp1)) {
- /* they match */
- namep++;
- continue;
- }
- /* if trying to match a star pattern, go back */
- if (sawStar) {
- maskp = starMaskp - 2;
- namep = starNamep + 1;
- sawStar = 0;
- continue;
- }
- /* that's all */
- return 0;
- }
- }
+ (!casefold && tcn1 == tcp1)) {
+ /* they match */
+ namep++;
+ continue;
+ }
+ /* if trying to match a star pattern, go back */
+ if (sawStar) {
+ maskp = starMaskp - 2;
+ namep = starNamep + 1;
+ sawStar = 0;
+ continue;
+ }
+ /* that's all */
+ return 0;
+ }
+ }
}
#endif /* USE_OLD_MATCHING */
long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx)
{
- int attribute;
+ int attribute;
long nextCookie;
char *tp;
- long code = 0;
+ long code = 0, code2 = 0;
char *pathp;
cm_dirEntry_t *dep;
int maxCount;
cm_scache_t *scp;
long entryInDir;
long entryInBuffer;
- cm_pageHeader_t *pageHeaderp;
+ cm_pageHeader_t *pageHeaderp;
cm_user_t *userp = NULL;
int slotInPage;
int returnedNames;
long nextEntryCookie;
int numDirChunks; /* # of 32 byte dir chunks in this entry */
char *op; /* output data ptr */
- char *origOp; /* original value of op */
+ char *origOp; /* original value of op */
cm_space_t *spacep; /* for pathname buffer */
long maxReturnData; /* max # of return data */
long maxReturnParms; /* max # of return parms */
int searchFlags;
int eos;
smb_tran2Packet_t *outp; /* response packet */
- char *tidPathp;
- int align;
- char shortName[13]; /* 8.3 name if needed */
- int NeedShortName;
+ char *tidPathp;
+ int align;
+ char shortName[13]; /* 8.3 name if needed */
+ int NeedShortName;
int foundInexact;
- char *shortNameEnd;
+ char *shortNameEnd;
int fileType;
cm_fid_t fid;
-
cm_req_t req;
- cm_InitReq(&req);
+ cm_InitReq(&req);
- eos = 0;
- if (p->opcode == 1) {
- /* find first; obtain basic parameters from request */
+ eos = 0;
+ if (p->opcode == 1) {
+ /* find first; obtain basic parameters from request */
attribute = p->parmsp[0];
maxCount = p->parmsp[1];
infoLevel = p->parmsp[3];
dsp = smb_NewDirSearch(1);
dsp->attribute = attribute;
pathp = ((char *) p->parmsp) + 12; /* points to path */
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
nextCookie = 0;
maskp = strrchr(pathp, '\\');
- if (maskp == NULL) maskp = pathp;
- else maskp++; /* skip over backslash */
+ if (maskp == NULL)
+ maskp = pathp;
+ else
+ maskp++; /* skip over backslash */
strcpy(dsp->mask, maskp); /* and save mask */
- /* track if this is likely to match a lot of entries */
+ /* track if this is likely to match a lot of entries */
starPattern = smb_V3IsStarMask(maskp);
- }
+ }
else {
- osi_assert(p->opcode == 2);
+ osi_assert(p->opcode == 2);
/* find next; obtain basic parameters from request or open dir file */
dsp = smb_FindDirSearch(p->parmsp[0]);
- if (!dsp) return CM_ERROR_BADFD;
- attribute = dsp->attribute;
maxCount = p->parmsp[1];
infoLevel = p->parmsp[2];
+ nextCookie = p->parmsp[3] | (p->parmsp[4] << 16);
searchFlags = p->parmsp[5];
+ if (!dsp) {
+ osi_Log2(smb_logp, "T2 search dir bad search ID: id %d nextCookie 0x%x",
+ p->parmsp[0], nextCookie);
+ return CM_ERROR_BADFD;
+ }
+ attribute = dsp->attribute;
pathp = NULL;
- nextCookie = p->parmsp[3] | (p->parmsp[4] << 16);
maskp = dsp->mask;
- starPattern = 1; /* assume, since required a Find Next */
+ starPattern = 1; /* assume, since required a Find Next */
}
- osi_Log4(smb_logp,
+ osi_Log4(smb_logp,
"T2 search dir attr 0x%x, info level %d, max count %d, flags 0x%x",
attribute, infoLevel, maxCount, searchFlags);
- osi_Log2(smb_logp, "...T2 search op %d, nextCookie 0x%x",
- p->opcode, nextCookie);
+ osi_Log3(smb_logp, "...T2 search op %d, id %d, nextCookie 0x%x",
+ p->opcode, dsp->cookie, nextCookie);
- if (infoLevel >= 0x101)
- searchFlags &= ~4; /* no resume keys */
+ if (infoLevel >= 0x101)
+ searchFlags &= ~4; /* no resume keys */
dirListPatchesp = NULL;
- maxReturnData = p->maxReturnData;
+ maxReturnData = p->maxReturnData;
if (p->opcode == 1) /* find first */
maxReturnParms = 10; /* bytes */
- else
+ else
maxReturnParms = 8; /* bytes */
#ifndef CM_CONFIG_MULTITRAN2RESPONSES
maxReturnData = 6000;
#endif /* CM_CONFIG_MULTITRAN2RESPONSES */
- outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
+ outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
maxReturnData);
- osi_Log1(smb_logp, "T2 receive search dir %s",
- osi_LogSaveString(smb_logp, pathp));
+ osi_Log2(smb_logp, "T2 receive search dir count %d [%s]",
+ maxCount, osi_LogSaveString(smb_logp, pathp));
/* bail out if request looks bad */
if (p->opcode == 1 && !pathp) {
return CM_ERROR_BADSMB;
}
- osi_Log2(smb_logp, "T2 dir search cookie 0x%x, connection %d",
- nextCookie, dsp->cookie);
+ osi_Log3(smb_logp, "T2 search dir id %d, nextCookie 0x%x, attr 0x%x",
+ dsp->cookie, nextCookie, attribute);
- userp = smb_GetTran2User(vcp, p);
+ userp = smb_GetTran2User(vcp, p);
if (!userp) {
- osi_Log1(smb_logp, "T2 dir search unable to resolve user [%d]", p->uid);
+ osi_Log1(smb_logp, "T2 search dir unable to resolve user [%d]", p->uid);
smb_ReleaseDirSearch(dsp);
smb_FreeTran2Packet(outp);
return CM_ERROR_BADSMB;
}
- /* try to get the vnode for the path name next */
- lock_ObtainMutex(&dsp->mx);
- if (dsp->scp) {
- scp = dsp->scp;
+ /* try to get the vnode for the path name next */
+ lock_ObtainMutex(&dsp->mx);
+ if (dsp->scp) {
+ scp = dsp->scp;
cm_HoldSCache(scp);
code = 0;
- }
- else {
- spacep = cm_GetSpace();
+ } else {
+ spacep = cm_GetSpace();
smb_StripLastComponent(spacep->data, NULL, pathp);
- lock_ReleaseMutex(&dsp->mx);
-
- code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
- if(code) {
- cm_ReleaseUser(userp);
+ code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
+ if (code) {
+ cm_ReleaseUser(userp);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOFILES);
smb_FreeTran2Packet(outp);
- smb_DeleteDirSearch(dsp);
- smb_ReleaseDirSearch(dsp);
+ lock_ReleaseMutex(&dsp->mx);
+ smb_DeleteDirSearch(dsp);
+ smb_ReleaseDirSearch(dsp);
return 0;
}
- code = cm_NameI(cm_rootSCachep, spacep->data,
+ code = cm_NameI(cm_data.rootSCachep, spacep->data,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
cm_FreeSpace(spacep);
- lock_ObtainMutex(&dsp->mx);
- if (code == 0) {
- if (dsp->scp != 0) cm_ReleaseSCache(dsp->scp);
- dsp->scp = scp;
- /* we need one hold for the entry we just stored into,
+ if (code == 0) {
+#ifdef DFS_SUPPORT_BUT_NOT_FIND_FIRST
+ if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(p) )
+ code = CM_ERROR_PATH_NOT_COVERED;
+ else
+ code = CM_ERROR_BADSHARENAME;
+ smb_SendTran2Error(vcp, p, opx, code);
+ smb_FreeTran2Packet(outp);
+ lock_ReleaseMutex(&dsp->mx);
+ smb_DeleteDirSearch(dsp);
+ smb_ReleaseDirSearch(dsp);
+ return 0;
+ }
+#endif /* DFS_SUPPORT */
+ dsp->scp = scp;
+ /* we need one hold for the entry we just stored into,
* and one for our own processing. When we're done
- * with this function, we'll drop the one for our own
- * processing. We held it once from the namei call,
- * and so we do another hold now.
+ * with this function, we'll drop the one for our own
+ * processing. We held it once from the namei call,
+ * and so we do another hold now.
*/
cm_HoldSCache(scp);
- lock_ObtainMutex(&scp->mx);
- if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0
- && LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
+ lock_ObtainMutex(&scp->mx);
+ if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0 &&
+ LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
- dsp->flags |= SMB_DIRSEARCH_BULKST;
- }
- lock_ReleaseMutex(&scp->mx);
- }
+ dsp->flags |= SMB_DIRSEARCH_BULKST;
+ }
+ lock_ReleaseMutex(&scp->mx);
+ }
}
- lock_ReleaseMutex(&dsp->mx);
+ lock_ReleaseMutex(&dsp->mx);
if (code) {
- cm_ReleaseUser(userp);
+ cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
- smb_DeleteDirSearch(dsp);
- smb_ReleaseDirSearch(dsp);
+ smb_DeleteDirSearch(dsp);
+ smb_ReleaseDirSearch(dsp);
return code;
- }
+ }
/* get the directory size */
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainMutex(&scp->mx);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code) {
- lock_ReleaseMutex(&scp->mx);
+ if (code) {
+ lock_ReleaseMutex(&scp->mx);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
- smb_DeleteDirSearch(dsp);
- smb_ReleaseDirSearch(dsp);
+ smb_DeleteDirSearch(dsp);
+ smb_ReleaseDirSearch(dsp);
return code;
}
bufferOffset.LowPart = bufferOffset.HighPart = 0;
curOffset.HighPart = 0;
curOffset.LowPart = nextCookie;
- origOp = outp->datap;
+ origOp = outp->datap;
foundInexact = 0;
code = 0;
returnedNames = 0;
bytesInBuffer = 0;
while (1) {
- op = origOp;
- if (searchFlags & 4)
- /* skip over resume key */
- op += 4;
+ op = origOp;
+ if (searchFlags & 4)
+ /* skip over resume key */
+ op += 4;
- /* make sure that curOffset.LowPart doesn't point to the first
+ /* make sure that curOffset.LowPart doesn't point to the first
* 32 bytes in the 2nd through last dir page, and that it doesn't
* point at the first 13 32-byte chunks in the first dir page,
* since those are dir and page headers, and don't contain useful
* information.
*/
- temp = curOffset.LowPart & (2048-1);
+ temp = curOffset.LowPart & (2048-1);
if (curOffset.HighPart == 0 && curOffset.LowPart < 2048) {
- /* we're in the first page */
+ /* we're in the first page */
if (temp < 13*32) temp = 13*32;
- }
- else {
- /* we're in a later dir page */
+ }
+ else {
+ /* we're in a later dir page */
if (temp < 32) temp = 32;
}
/* check if we've passed the dir's EOF */
if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
+ osi_Log0(smb_logp, "T2 search dir passed eof");
eos = 1;
break;
}
* the dir entry, since we'll need to check its size.
*/
if (returnedNames >= maxCount) {
+ osi_Log2(smb_logp, "T2 search dir returnedNames %d >= maxCount %d",
+ returnedNames, maxCount);
break;
}
* the offset of the buffer we have. If not, get the buffer.
*/
thyper.HighPart = curOffset.HighPart;
- thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
+ thyper.LowPart = curOffset.LowPart & ~(cm_data.buf_blockSize-1);
if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
- /* wrong buffer */
+ /* wrong buffer */
if (bufferp) {
buf_Release(bufferp);
bufferp = NULL;
- }
- lock_ReleaseMutex(&scp->mx);
- lock_ObtainRead(&scp->bufCreateLock);
+ }
+ lock_ReleaseMutex(&scp->mx);
+ lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
- lock_ReleaseRead(&scp->bufCreateLock);
+ lock_ReleaseRead(&scp->bufCreateLock);
+ lock_ObtainMutex(&dsp->mx);
- /* now, if we're doing a star match, do bulk fetching
- * of all of the status info for files in the dir.
+ /* now, if we're doing a star match, do bulk fetching
+ * of all of the status info for files in the dir.
*/
if (starPattern) {
- smb_ApplyV3DirListPatches(scp, &dirListPatchesp,
- infoLevel, userp,
- &req);
- if ((dsp->flags & SMB_DIRSEARCH_BULKST)
- && LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
- /* Don't bulk stat if risking timeout */
- int now = GetCurrentTime();
- if (now - req.startTime > 5000) {
- scp->bulkStatProgress = thyper;
- scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
- dsp->flags &= ~SMB_DIRSEARCH_BULKST;
- } else
+ smb_ApplyV3DirListPatches(scp, &dirListPatchesp,
+ infoLevel, userp,
+ &req);
+ lock_ObtainMutex(&scp->mx);
+ if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
+ LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
+ /* Don't bulk stat if risking timeout */
+ int now = GetCurrentTime();
+ if (now - req.startTime > 5000) {
+ scp->bulkStatProgress = thyper;
+ scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
+ dsp->flags &= ~SMB_DIRSEARCH_BULKST;
+ } else
cm_TryBulkStat(scp, &thyper, userp, &req);
- }
- }
+ }
+ } else {
+ lock_ObtainMutex(&scp->mx);
+ }
+ lock_ReleaseMutex(&dsp->mx);
+ if (code) {
+ osi_Log2(smb_logp, "T2 search dir buf_Get scp %x failed %d", scp, code);
+ break;
+ }
- lock_ObtainMutex(&scp->mx);
- if (code) break;
bufferOffset = thyper;
/* now get the data in the cache */
while (1) {
- code = cm_SyncOp(scp, bufferp, userp, &req,
+ code = cm_SyncOp(scp, bufferp, userp, &req,
PRSFS_LOOKUP,
CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_READ);
- if (code) break;
+ if (code) {
+ osi_Log2(smb_logp, "T2 search dir cm_SyncOp scp %x failed %d", scp, code);
+ break;
+ }
- if (cm_HaveBuffer(scp, bufferp, 0)) break;
+ if (cm_HaveBuffer(scp, bufferp, 0)) {
+ osi_Log2(smb_logp, "T2 search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
+ break;
+ }
/* otherwise, load the buffer and try again */
code = cm_GetBuffer(scp, bufferp, NULL, userp,
&req);
- if (code) break;
+ if (code) {
+ osi_Log3(smb_logp, "T2 search dir cm_GetBuffer failed scp %x bufferp %x code %d",
+ scp, bufferp, code);
+ break;
+ }
}
if (code) {
- buf_Release(bufferp);
+ buf_Release(bufferp);
bufferp = NULL;
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.
*/
- entryInDir = curOffset.LowPart & (2048-1);
- entryInBuffer = curOffset.LowPart & (buf_bufferSize - 1);
+ entryInDir = curOffset.LowPart & (2048-1);
+ entryInBuffer = curOffset.LowPart & (cm_data.buf_blockSize - 1);
- /* page header will help tell us which entries are free. Page
- * header can change more often than once per buffer, since
- * AFS 3 dir page size may be less than (but not more than)
- * a buffer package buffer.
+ /* page header will help tell us which entries are free. Page
+ * header can change more often than once per buffer, since
+ * AFS 3 dir page size may be less than (but not more than)
+ * a buffer package buffer.
*/
- /* only look intra-buffer */
- temp = curOffset.LowPart & (buf_bufferSize - 1);
+ /* only look intra-buffer */
+ temp = curOffset.LowPart & (cm_data.buf_blockSize - 1);
temp &= ~(2048 - 1); /* turn off intra-page bits */
- pageHeaderp = (cm_pageHeader_t *) (bufferp->datap + temp);
+ pageHeaderp = (cm_pageHeader_t *) (bufferp->datap + temp);
- /* now determine which entry we're looking at in the page.
- * If it is free (there's a free bitmap at the start of the
- * dir), we should skip these 32 bytes.
+ /* now determine which entry we're looking at in the page.
+ * If it is free (there's a free bitmap at the start of the
+ * dir), we should skip these 32 bytes.
*/
slotInPage = (entryInDir & 0x7e0) >> 5;
- if (!(pageHeaderp->freeBitmap[slotInPage>>3]
- & (1 << (slotInPage & 0x7)))) {
- /* this entry is free */
+ if (!(pageHeaderp->freeBitmap[slotInPage>>3] &
+ (1 << (slotInPage & 0x7)))) {
+ /* this entry is free */
numDirChunks = 1; /* only skip this guy */
goto nextEntry;
}
- tp = bufferp->datap + entryInBuffer;
+ tp = bufferp->datap + entryInBuffer;
dep = (cm_dirEntry_t *) tp; /* now points to AFS3 dir entry */
/* while we're here, compute the next entry's location, too,
- * since we'll need it when writing out the cookie into the dir
- * listing stream.
+ * since we'll need it when writing out the cookie into the dir
+ * listing stream.
*
* XXXX Probably should do more sanity checking.
*/
- numDirChunks = cm_NameEntries(dep->name, &onbytes);
+ numDirChunks = cm_NameEntries(dep->name, &onbytes);
/* compute offset of cookie representing next entry */
nextEntryCookie = curOffset.LowPart + (CM_DIR_CHUNKSIZE * numDirChunks);
- /* Need 8.3 name? */
- NeedShortName = 0;
- if (infoLevel == 0x104
- && dep->fid.vnode != 0
- && !cm_Is8Dot3(dep->name)) {
- cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
- NeedShortName = 1;
- }
+ /* Need 8.3 name? */
+ NeedShortName = 0;
+ if (infoLevel == SMB_QUERY_FILE_NAME_INFO
+ && dep->fid.vnode != 0
+ && !cm_Is8Dot3(dep->name)) {
+ cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
+ NeedShortName = 1;
+ }
+
+ osi_Log3(smb_logp, "T2 search dir vn %u name %s (%s)",
+ dep->fid.vnode, osi_LogSaveString(smb_logp, dep->name),
+ NeedShortName ? osi_LogSaveString(smb_logp, shortName) : "");
/* When matching, we are using doing a case fold if we have a wildcard mask.
* If we get a non-wildcard match, it's a lookup for a specific file.
*/
if (dep->fid.vnode != 0 &&
- (smb_V3MatchMask(dep->name, maskp, (starPattern? CM_FLAG_CASEFOLD : 0))
- || (NeedShortName
- && smb_V3MatchMask(shortName, maskp, CM_FLAG_CASEFOLD)))) {
+ (smb_V3MatchMask(dep->name, maskp, (starPattern? CM_FLAG_CASEFOLD : 0)) ||
+ (NeedShortName &&
+ smb_V3MatchMask(shortName, maskp, CM_FLAG_CASEFOLD)))) {
/* Eliminate entries that don't match requested attributes */
if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) &&
- smb_IsDotFile(dep->name))
+ smb_IsDotFile(dep->name)) {
+ osi_Log0(smb_logp, "T2 search dir skipping hidden");
goto nextEntry; /* no hidden files */
-
+ }
if (!(dsp->attribute & SMB_ATTR_DIRECTORY)) /* no directories */
{
/* We have already done the cm_TryBulkStat above */
/*osi_Log2(smb_logp, "smb_ReceiveTran2SearchDir: file %s "
"has filetype %d", dep->name,
fileType);*/
- if (fileType == CM_SCACHETYPE_DIRECTORY)
+ if (fileType == CM_SCACHETYPE_DIRECTORY ||
+ fileType == CM_SCACHETYPE_DFSLINK ||
+ fileType == CM_SCACHETYPE_INVALID)
+ osi_Log0(smb_logp, "T2 search dir skipping directory or bad link");
goto nextEntry;
}
- /* finally check if this name will fit */
+ /* finally check if this name will fit */
- /* standard dir entry stuff */
- if (infoLevel < 0x101)
- ohbytes = 23; /* pre-NT */
- else if (infoLevel == 0x103)
- ohbytes = 12; /* NT names only */
- else
- ohbytes = 64; /* NT */
+ /* standard dir entry stuff */
+ if (infoLevel < 0x101)
+ ohbytes = 23; /* pre-NT */
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+ ohbytes = 12; /* NT names only */
+ else
+ ohbytes = 64; /* NT */
- if (infoLevel == 0x104)
- ohbytes += 26; /* Short name & length */
+ if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
+ ohbytes += 26; /* Short name & length */
if (searchFlags & 4) {
ohbytes += 4; /* if resume key required */
- }
+ }
if (infoLevel != 1
&& infoLevel != 0x101
&& infoLevel != 0x103)
- ohbytes += 4; /* EASIZE */
+ ohbytes += 4; /* EASIZE */
- /* add header to name & term. null */
- orbytes = onbytes + ohbytes + 1;
+ /* add header to name & term. null */
+ orbytes = onbytes + ohbytes + 1;
- /* now, we round up the record to a 4 byte alignment,
- * and we make sure that we have enough room here for
- * even the aligned version (so we don't have to worry
- * about an * overflow when we pad things out below).
- * That's the reason for the alignment arithmetic below.
+ /* now, we round up the record to a 4 byte alignment,
+ * and we make sure that we have enough room here for
+ * even the aligned version (so we don't have to worry
+ * about an * overflow when we pad things out below).
+ * That's the reason for the alignment arithmetic below.
*/
- if (infoLevel >= 0x101)
- align = (4 - (orbytes & 3)) & 3;
- else
- align = 0;
- if (orbytes + bytesInBuffer + align > maxReturnData)
+ if (infoLevel >= 0x101)
+ align = (4 - (orbytes & 3)) & 3;
+ else
+ align = 0;
+ if (orbytes + bytesInBuffer + align > maxReturnData) {
+ osi_Log1(smb_logp, "T2 dir search exceed max return data %d",
+ maxReturnData);
break;
+ }
- /* this is one of the entries to use: it is not deleted
- * and it matches the star pattern we're looking for.
- * Put out the name, preceded by its length.
+ /* this is one of the entries to use: it is not deleted
+ * and it matches the star pattern we're looking for.
+ * Put out the name, preceded by its length.
*/
- /* First zero everything else */
- memset(origOp, 0, ohbytes);
+ /* First zero everything else */
+ memset(origOp, 0, ohbytes);
- if (infoLevel <= 0x101)
+ if (infoLevel <= 0x101)
*(origOp + ohbytes - 1) = (unsigned char) onbytes;
- else if (infoLevel == 0x103)
- *((u_long *)(op + 8)) = onbytes;
- else
- *((u_long *)(op + 60)) = onbytes;
+ else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+ *((u_long *)(op + 8)) = onbytes;
+ else
+ *((u_long *)(op + 60)) = onbytes;
strcpy(origOp+ohbytes, dep->name);
-
- /* Short name if requested and needed */
- if (infoLevel == 0x104) {
- if (NeedShortName) {
- strcpy(op + 70, shortName);
- *(op + 68) = shortNameEnd - shortName;
- }
- }
+ if (smb_StoreAnsiFilenames)
+ CharToOem(origOp+ohbytes, origOp+ohbytes);
+
+ /* Short name if requested and needed */
+ if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
+ if (NeedShortName) {
+ strcpy(op + 70, shortName);
+ if (smb_StoreAnsiFilenames)
+ CharToOem(op + 70, op + 70);
+ *(op + 68) = shortNameEnd - shortName;
+ }
+ }
/* now, adjust the # of entries copied */
returnedNames++;
- /* NextEntryOffset and FileIndex */
- if (infoLevel >= 101) {
- int entryOffset = orbytes + align;
- *((u_long *)op) = entryOffset;
- *((u_long *)(op+4)) = nextEntryCookie;
- }
+ /* NextEntryOffset and FileIndex */
+ if (infoLevel >= 101) {
+ int entryOffset = orbytes + align;
+ *((u_long *)op) = entryOffset;
+ *((u_long *)(op+4)) = nextEntryCookie;
+ }
/* now we emit the attribute. This is tricky, since
* we need to really stat the file to find out what
- * type of entry we've got. Right now, we're copying
- * out data from * a buffer, while holding the scp
- * locked, so it isn't really convenient to stat
- * something now. We'll put in a place holder
+ * type of entry we've got. Right now, we're copying
+ * out data from a buffer, while holding the scp
+ * locked, so it isn't really convenient to stat
+ * something now. We'll put in a place holder
* now, and make a second pass before returning this
- * to get the real attributes. So, we just skip the
- * data for now, and adjust it later. We allocate a
- * patch record to make it easy to find this point
- * later. The replay will happen at a time when it is
- * safe to unlock the directory.
+ * to get the real attributes. So, we just skip the
+ * data for now, and adjust it later. We allocate a
+ * patch record to make it easy to find this point
+ * later. The replay will happen at a time when it is
+ * safe to unlock the directory.
*/
- if (infoLevel != 0x103) {
- curPatchp = malloc(sizeof(*curPatchp));
+ if (infoLevel != 0x103) {
+ curPatchp = malloc(sizeof(*curPatchp));
osi_QAdd((osi_queue_t **) &dirListPatchesp,
&curPatchp->q);
- curPatchp->dptr = op;
- if (infoLevel >= 0x101)
- curPatchp->dptr += 8;
+ curPatchp->dptr = op;
+ if (infoLevel >= 0x101)
+ curPatchp->dptr += 8;
if (smb_hideDotFiles && smb_IsDotFile(dep->name)) {
curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE;
- }
- else
+ }
+ else
curPatchp->flags = 0;
- curPatchp->fid.cell = scp->fid.cell;
- curPatchp->fid.volume = scp->fid.volume;
- curPatchp->fid.vnode = ntohl(dep->fid.vnode);
- curPatchp->fid.unique = ntohl(dep->fid.unique);
+ curPatchp->fid.cell = scp->fid.cell;
+ curPatchp->fid.volume = scp->fid.volume;
+ curPatchp->fid.vnode = ntohl(dep->fid.vnode);
+ curPatchp->fid.unique = ntohl(dep->fid.unique);
/* temp */
curPatchp->dep = dep;
- }
+ }
- if (searchFlags & 4)
- /* put out resume key */
- *((u_long *)origOp) = nextEntryCookie;
+ if (searchFlags & 4)
+ /* put out resume key */
+ *((u_long *)origOp) = nextEntryCookie;
- /* Adjust byte ptr and count */
- origOp += orbytes; /* skip entire record */
+ /* Adjust byte ptr and count */
+ origOp += orbytes; /* skip entire record */
bytesInBuffer += orbytes;
- /* and pad the record out */
+ /* and pad the record out */
while (--align >= 0) {
- *origOp++ = 0;
+ *origOp++ = 0;
bytesInBuffer++;
}
-
- } /* if we're including this name */
- else if (!NeedShortName &&
- !starPattern &&
+ } /* if we're including this name */
+ else if (!starPattern &&
!foundInexact &&
- dep->fid.vnode != 0 &&
+ dep->fid.vnode != 0 &&
smb_V3MatchMask(dep->name, maskp, CM_FLAG_CASEFOLD)) {
/* We were looking for exact matches, but here's an inexact one*/
foundInexact = 1;
nextEntry:
/* and adjust curOffset to be where the new cookie is */
- thyper.HighPart = 0;
+ thyper.HighPart = 0;
thyper.LowPart = CM_DIR_CHUNKSIZE * numDirChunks;
curOffset = LargeIntegerAdd(thyper, curOffset);
- } /* while copying data for dir listing */
+ } /* while copying data for dir listing */
/* 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
goto startsearch;
}
- /* release the mutex */
- lock_ReleaseMutex(&scp->mx);
- if (bufferp) buf_Release(bufferp);
+ /* release the mutex */
+ lock_ReleaseMutex(&scp->mx);
+ if (bufferp)
+ buf_Release(bufferp);
- /* apply and free last set of patches; if not doing a star match, this
- * will be empty, but better safe (and freeing everything) than sorry.
+ /* apply and free last set of patches; if not doing a star match, this
+ * will be empty, but better safe (and freeing everything) than sorry.
*/
- smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp,
+ code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp,
&req);
/* now put out the final parameters */
- if (returnedNames == 0) eos = 1;
+ if (returnedNames == 0)
+ eos = 1;
if (p->opcode == 1) {
- /* find first */
+ /* find first */
outp->parmsp[0] = (unsigned short) dsp->cookie;
outp->parmsp[1] = returnedNames;
outp->parmsp[2] = eos;
outp->totalParms = 8; /* in bytes */
}
- /* return # of bytes in the buffer */
+ /* return # of bytes in the buffer */
outp->totalData = bytesInBuffer;
- osi_Log2(smb_logp, "T2 search dir done, %d names, code %d",
- returnedNames, code);
+ /* Return error code if unsuccessful on first request */
+ if (code == 0 && p->opcode == 1 && returnedNames == 0)
+ code = CM_ERROR_NOSUCHFILE;
- /* Return error code if unsuccessful on first request */
- if (code == 0 && p->opcode == 1 && returnedNames == 0)
- code = CM_ERROR_NOSUCHFILE;
+ osi_Log4(smb_logp, "T2 search dir done, opcode %d, id %d, %d names, code %d",
+ p->opcode, dsp->cookie, returnedNames, code);
- /* if we're supposed to close the search after this request, or if
+ /* if we're supposed to close the search after this request, or if
* we're supposed to close the search if we're done, and we're done,
* or if something went wrong, close the search.
*/
/* ((searchFlags & 1) || ((searchFlags & 2) && eos) */
- if ((searchFlags & 1) || (returnedNames == 0) ||
+ if ((searchFlags & 1) || (returnedNames == 0) ||
((searchFlags & 2) && eos) || code != 0)
- smb_DeleteDirSearch(dsp);
- if (code)
+ smb_DeleteDirSearch(dsp);
+ if (code)
smb_SendTran2Error(vcp, p, opx, code);
- else {
+ else
smb_SendTran2Packet(vcp, outp, opx);
- }
- smb_FreeTran2Packet(outp);
+
+ smb_FreeTran2Packet(outp);
smb_ReleaseDirSearch(dsp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
dsp = smb_FindDirSearch(dirHandle);
if (!dsp)
- return CM_ERROR_BADFD;
+ return CM_ERROR_BADFD;
/* otherwise, we have an FD to destroy */
smb_DeleteDirSearch(dsp);
smb_ReleaseDirSearch(dsp);
- /* and return results */
- smb_SetSMBDataLength(outp, 0);
+ /* and return results */
+ smb_SetSMBDataLength(outp, 0);
return 0;
}
long smb_ReceiveV3FindNotifyClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- smb_SetSMBDataLength(outp, 0);
+ smb_SetSMBDataLength(outp, 0);
return 0;
}
long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- char *pathp;
+ char *pathp;
long code = 0;
- cm_space_t *spacep;
+ cm_space_t *spacep;
int excl;
cm_user_t *userp;
cm_scache_t *dscp; /* dir we're dealing with */
smb_fid_t *fidp;
int attributes;
char *lastNamep;
- time_t dosTime;
+ afs_uint32 dosTime;
int openFun;
int trunc;
int openMode;
int extraInfo;
int openAction;
int parmSlot; /* which parm we're dealing with */
- char *tidPathp;
- cm_req_t req;
+ char *tidPathp;
+ cm_req_t req;
- cm_InitReq(&req);
+ cm_InitReq(&req);
scp = NULL;
- extraInfo = (smb_GetSMBParm(inp, 2) & 1); /* return extra info */
- openFun = smb_GetSMBParm(inp, 8); /* open function */
+ extraInfo = (smb_GetSMBParm(inp, 2) & 1); /* return extra info */
+ openFun = smb_GetSMBParm(inp, 8); /* open function */
excl = ((openFun & 3) == 0);
- trunc = ((openFun & 3) == 2); /* truncate it */
- openMode = (smb_GetSMBParm(inp, 3) & 0x7);
- openAction = 0; /* tracks what we did */
+ trunc = ((openFun & 3) == 2); /* truncate it */
+ openMode = (smb_GetSMBParm(inp, 3) & 0x7);
+ openAction = 0; /* tracks what we did */
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 */
+ /* compute initial mode bits based on read-only flag in attributes */
initialModeBits = 0666;
if (attributes & 1) initialModeBits &= ~0222;
pathp = smb_GetSMBData(inp, NULL);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(pathp,pathp);
- spacep = inp->spacep;
+ spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
- /* special case magic file name for receiving IOCTL requests
+ if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
+ /* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
#ifdef NOTSERVICE
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
smb_SetupIoctlFid(fidp, spacep);
- /* set inp->fid so that later read calls in same msg can find 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++;
- if (extraInfo) {
+ parmSlot = 2;
+ smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
+ if (extraInfo) {
smb_SetSMBParm(outp, parmSlot, /* attrs */ 0); parmSlot++;
smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* mod time */
smb_SetSMBParm(outp, parmSlot, 0); 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 */
- }
- /* and the final "always present" stuff */
+ }
+ /* and the final "always present" stuff */
smb_SetSMBParm(outp, parmSlot, /* openAction found existing file */ 1); parmSlot++;
- /* next write out the "unique" ID */
- smb_SetSMBParm(outp, parmSlot, 0x1234); parmSlot++;
- smb_SetSMBParm(outp, parmSlot, 0x5678); parmSlot++;
+ /* next write out the "unique" ID */
+ smb_SetSMBParm(outp, parmSlot, 0x1234); parmSlot++;
+ smb_SetSMBParm(outp, parmSlot, 0x5678); parmSlot++;
smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
smb_SetSMBDataLength(outp, 0);
- /* and clean up fid reference */
+ /* and clean up fid reference */
smb_ReleaseFID(fidp);
return 0;
}
#endif
userp = smb_GetUser(vcp, inp);
- dscp = NULL;
- code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
- if(code) {
+ dscp = NULL;
+ code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+ if (code) {
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_rootSCachep, pathp,
+ code = cm_NameI(cm_data.rootSCachep, pathp,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
- if (code != 0) {
- code = cm_NameI(cm_rootSCachep, spacep->data,
+
+#ifdef DFS_SUPPORT
+ if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
+ if (code != 0) {
+ code = cm_NameI(cm_data.rootSCachep, spacep->data,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
-
if (code) {
cm_ReleaseUser(userp);
return code;
}
-
+
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
/* otherwise, scp points to the parent directory. Do a lookup,
* and truncate the file if we find it, otherwise we create the
* file.
*/
- if (!lastNamep) lastNamep = pathp;
- else lastNamep++;
+ if (!lastNamep)
+ lastNamep = pathp;
+ else
+ lastNamep++;
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
&req, &scp);
if (code && code != CM_ERROR_NOSUCHFILE) {
- cm_ReleaseSCache(dscp);
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
return code;
}
- }
+ }
/* if 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,
* scp is NULL.
*/
- if (code == 0) {
+ if (code == 0) {
code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
if (code) {
if (dscp) cm_ReleaseSCache(dscp);
return code;
}
- if (excl) {
- /* oops, file shouldn't be there */
- if (dscp) cm_ReleaseSCache(dscp);
- cm_ReleaseSCache(scp);
- cm_ReleaseUser(userp);
+ if (excl) {
+ /* oops, file shouldn't be there */
+ if (dscp)
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
return CM_ERROR_EXISTS;
}
- if (trunc) {
- setAttr.mask = CM_ATTRMASK_LENGTH;
+ if (trunc) {
+ setAttr.mask = CM_ATTRMASK_LENGTH;
setAttr.length.LowPart = 0;
setAttr.length.HighPart = 0;
- code = cm_SetAttr(scp, &setAttr, userp, &req);
+ code = cm_SetAttr(scp, &setAttr, userp, &req);
openAction = 3; /* truncated existing file */
- }
+ }
else openAction = 1; /* found existing file */
}
- else if (!(openFun & 0x10)) {
- /* don't create if not found */
+ else if (!(openFun & SMB_ATTR_DIRECTORY)) {
+ /* don't create if not found */
if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHFILE;
}
else {
- osi_assert(dscp != NULL);
- osi_Log1(smb_logp, "smb_ReceiveV3OpenX creating file %s",
+ osi_assert(dscp != NULL);
+ osi_Log1(smb_logp, "smb_ReceiveV3OpenX creating file %s",
osi_LogSaveString(smb_logp, lastNamep));
- openAction = 2; /* created file */
- setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
- smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
+ openAction = 2; /* created file */
+ setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
+ smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_ADDED,
+ if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+ smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, lastNamep, NULL, TRUE);
if (!excl && code == CM_ERROR_EXISTS) {
- /* not an exclusive create, and someone else tried
- * creating it already, then we open it anyway. We
- * don't bother retrying after this, since if this next
- * fails, that means that the file was deleted after we
- * started this call.
+ /* not an exclusive create, and someone else tried
+ * creating it already, then we open it anyway. We
+ * don't bother retrying after this, since if this next
+ * fails, that means that the file was deleted after we
+ * started this call.
*/
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
userp, &req, &scp);
if (code == 0) {
if (trunc) {
- setAttr.mask = CM_ATTRMASK_LENGTH;
+ setAttr.mask = CM_ATTRMASK_LENGTH;
setAttr.length.LowPart = 0;
setAttr.length.HighPart = 0;
code = cm_SetAttr(scp, &setAttr, userp, &req);
}
- } /* lookup succeeded */
+ } /* lookup succeeded */
}
}
- /* we don't need this any longer */
- if (dscp) cm_ReleaseSCache(dscp);
+ /* we don't need this any longer */
+ if (dscp)
+ cm_ReleaseSCache(dscp);
if (code) {
- /* something went wrong creating or truncating the file */
- if (scp) cm_ReleaseSCache(scp);
+ /* something went wrong creating or truncating the file */
+ 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);
- cm_ReleaseUser(userp);
- return CM_ERROR_ISDIR;
- }
+ /* make sure we're about to open a file */
+ if (scp->fileType != CM_SCACHETYPE_FILE) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ return CM_ERROR_ISDIR;
+ }
/* now all we have to do is open the file itself */
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
osi_assert(fidp);
- /* save a pointer to the vnode */
+ /* save a pointer to the vnode */
fidp->scp = scp;
- /* compute open mode */
- if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
+ /* compute open mode */
+ if (openMode != 1)
+ fidp->flags |= SMB_FID_OPENREAD;
if (openMode == 1 || openMode == 2)
fidp->flags |= SMB_FID_OPENWRITE;
- smb_ReleaseFID(fidp);
+ smb_ReleaseFID(fidp);
- cm_Open(scp, 0, userp);
+ cm_Open(scp, 0, userp);
- /* set inp->fid so that later read calls in same msg can find 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++;
- lock_ObtainMutex(&scp->mx);
- if (extraInfo) {
+ parmSlot = 2;
+ smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
+ lock_ObtainMutex(&scp->mx);
+ if (extraInfo) {
smb_SetSMBParm(outp, parmSlot, smb_Attributes(scp)); parmSlot++;
- smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
+ smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
smb_SetSMBParm(outp, parmSlot, dosTime & 0xffff); parmSlot++;
smb_SetSMBParm(outp, parmSlot, (dosTime>>16) & 0xffff); parmSlot++;
smb_SetSMBParm(outp, parmSlot, scp->length.LowPart & 0xffff); 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 */
- }
- /* and the final "always present" stuff */
+ }
+ /* and the final "always present" stuff */
smb_SetSMBParm(outp, parmSlot, openAction); parmSlot++;
- /* next write out the "unique" ID */
- smb_SetSMBParm(outp, parmSlot, scp->fid.vnode & 0xffff); parmSlot++;
- smb_SetSMBParm(outp, parmSlot, scp->fid.volume & 0xffff); parmSlot++;
+ /* next write out the "unique" ID */
+ smb_SetSMBParm(outp, parmSlot, scp->fid.vnode & 0xffff); parmSlot++;
+ smb_SetSMBParm(outp, parmSlot, scp->fid.volume & 0xffff); parmSlot++;
smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseMutex(&scp->mx);
smb_SetSMBDataLength(outp, 0);
- osi_Log1(smb_logp, "SMB OpenX opening fid %d", fidp->fid);
+ osi_Log1(smb_logp, "SMB OpenX opening fid %d", fidp->fid);
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,
+ LARGE_INTEGER * pLength)
+{
+ if (LockType & LOCKING_ANDX_LARGE_FILES) {
+ /* Large Files */
+ *ppid = *((USHORT *) *buf);
+ pOffset->HighPart = *((LONG *)(*buf + 4));
+ pOffset->LowPart = *((DWORD *)(*buf + 8));
+ pLength->HighPart = *((LONG *)(*buf + 12));
+ pLength->LowPart = *((DWORD *)(*buf + 16));
+ *buf += 20;
+ }
+ else {
+ /* Not Large Files */
+ *ppid = *((USHORT *) *buf);
+ pOffset->HighPart = 0;
+ pOffset->LowPart = *((DWORD *)(*buf + 2));
+ pLength->HighPart = 0;
+ pLength->LowPart = *((DWORD *)(*buf + 6));
+ *buf += 10;
+ }
+}
long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- cm_req_t req;
- cm_user_t *userp;
- unsigned short fid;
- smb_fid_t *fidp;
- cm_scache_t *scp;
- unsigned char LockType;
- unsigned short NumberOfUnlocks, NumberOfLocks;
- unsigned long Timeout;
- char *op;
- LARGE_INTEGER LOffset, LLength;
- smb_waitingLock_t *waitingLock;
- void *lockp;
- long code = 0;
- int i;
-
- cm_InitReq(&req);
-
- fid = smb_GetSMBParm(inp, 2);
- fid = smb_ChainFID(fid, inp);
-
- fidp = smb_FindFID(vcp, fid, 0);
- if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
- return CM_ERROR_BADFD;
- }
- /* set inp->fid so that later read calls in same msg can find fid */
+ cm_req_t req;
+ cm_user_t *userp;
+ unsigned short fid;
+ smb_fid_t *fidp;
+ cm_scache_t *scp;
+ unsigned char LockType;
+ unsigned short NumberOfUnlocks, NumberOfLocks;
+ long Timeout;
+ char *op;
+ char *op_locks;
+ LARGE_INTEGER LOffset, LLength;
+ smb_waitingLockRequest_t *wlRequest = NULL;
+ cm_file_lock_t *lockp;
+ long code = 0;
+ int i;
+ cm_key_t key;
+ unsigned int pid;
+
+ cm_InitReq(&req);
+
+ fid = smb_GetSMBParm(inp, 2);
+ fid = smb_ChainFID(fid, inp);
+
+ fidp = smb_FindFID(vcp, fid, 0);
+ if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+ osi_Log0(smb_logp, "smb_ReceiveV3Locking BadFD");
+ return CM_ERROR_BADFD;
+ }
+ /* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fid;
- userp = smb_GetUser(vcp, inp);
+ userp = smb_GetUser(vcp, inp);
- scp = fidp->scp;
+ scp = fidp->scp;
- lock_ObtainMutex(&scp->mx);
- code = cm_SyncOp(scp, NULL, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK
+ lock_ObtainMutex(&scp->mx);
+ code = cm_SyncOp(scp, NULL, userp, &req, 0,
+ CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_GETSTATUS
| CM_SCACHESYNC_LOCK);
- if (code) goto doneSync;
-
- LockType = smb_GetSMBParm(inp, 3) & 0xff;
- Timeout = (smb_GetSMBParm(inp, 5) << 16) + smb_GetSMBParm(inp, 4);
- NumberOfUnlocks = smb_GetSMBParm(inp, 6);
- NumberOfLocks = smb_GetSMBParm(inp, 7);
-
- op = smb_GetSMBData(inp, NULL);
-
- for (i=0; i<NumberOfUnlocks; i++) {
- if (LockType & 0x10) {
- /* Large Files */
- LOffset.HighPart = *((LONG *)(op + 4));
- LOffset.LowPart = *((DWORD *)(op + 8));
- LLength.HighPart = *((LONG *)(op + 12));
- LLength.LowPart = *((DWORD *)(op + 16));
- op += 20;
- }
- else {
- /* Not Large Files */
- LOffset.HighPart = 0;
- LOffset.LowPart = *((DWORD *)(op + 2));
- LLength.HighPart = 0;
- LLength.LowPart = *((DWORD *)(op + 6));
- op += 10;
- }
- if (LargeIntegerNotEqualToZero(LOffset))
- continue;
- /* Do not check length -- length check done in cm_Unlock */
-
- code = cm_Unlock(scp, LockType, LOffset, LLength, userp, &req);
- if (code) goto done;
- }
+ if (code) {
+ osi_Log1(smb_logp, "smb_ReceiveV3Locking SyncOp failure code 0x%x", code);
+ goto doneSync;
+ }
- for (i=0; i<NumberOfLocks; i++) {
- if (LockType & 0x10) {
- /* Large Files */
- LOffset.HighPart = *((LONG *)(op + 4));
- LOffset.LowPart = *((DWORD *)(op + 8));
- LLength.HighPart = *((LONG *)(op + 12));
- LLength.LowPart = *((DWORD *)(op + 16));
- op += 20;
- }
- else {
- /* Not Large Files */
- LOffset.HighPart = 0;
- LOffset.LowPart = *((DWORD *)(op + 2));
- LLength.HighPart = 0;
- LLength.LowPart = *((DWORD *)(op + 6));
- op += 10;
- }
- if (LargeIntegerNotEqualToZero(LOffset))
- continue;
- if (LargeIntegerLessThan(LOffset, scp->length))
- continue;
-
- code = cm_Lock(scp, LockType, LOffset, LLength, Timeout,
- userp, &req, &lockp);
- if (code == CM_ERROR_WOULDBLOCK && Timeout != 0) {
- /* Put on waiting list */
- waitingLock = malloc(sizeof(smb_waitingLock_t));
- waitingLock->vcp = vcp;
- waitingLock->inp = smb_CopyPacket(inp);
- waitingLock->outp = smb_CopyPacket(outp);
- waitingLock->timeRemaining = Timeout;
- waitingLock->lockp = lockp;
- lock_ObtainWrite(&smb_globalLock);
- osi_QAdd((osi_queue_t **)&smb_allWaitingLocks,
- &waitingLock->q);
- osi_Wakeup((long) &smb_allWaitingLocks);
- lock_ReleaseWrite(&smb_globalLock);
- /* don't send reply immediately */
- outp->flags |= SMB_PACKETFLAG_NOSEND;
- }
- if (code) break;
- }
+ LockType = smb_GetSMBParm(inp, 3) & 0xff;
+ Timeout = (smb_GetSMBParm(inp, 5) << 16) + smb_GetSMBParm(inp, 4);
+ NumberOfUnlocks = smb_GetSMBParm(inp, 6);
+ NumberOfLocks = smb_GetSMBParm(inp, 7);
- if (code) {
- /* release any locks acquired before the failure */
- }
- else
- smb_SetSMBDataLength(outp, 0);
-done:
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
-doneSync:
- lock_ReleaseMutex(&scp->mx);
- cm_ReleaseUser(userp);
- smb_ReleaseFID(fidp);
-
- return code;
+ if ((LockType & LOCKING_ANDX_CANCEL_LOCK) ||
+ (LockType & LOCKING_ANDX_CHANGE_LOCKTYPE)) {
+
+ /* We don't support these requests. Apparently, we can safely
+ not deal with them too. */
+ osi_Log1(smb_logp, "smb_ReceiveV3Locking received unsupported request [%s]",
+ ((LockType & LOCKING_ANDX_CANCEL_LOCK)?
+ "LOCKING_ANDX_CANCEL_LOCK":
+ "LOCKING_ANDX_CHANGE_LOCKTYPE"));
+ /* No need to call osi_LogSaveString since these are string
+ constants.*/
+
+ code = CM_ERROR_BADOP;
+ goto done;
+
+ }
+
+ op = smb_GetSMBData(inp, NULL);
+
+ for (i=0; i<NumberOfUnlocks; i++) {
+ smb_GetLockParams(LockType, &op, &pid, &LOffset, &LLength);
+
+ key = cm_GenerateKey(vcp->vcID, pid, fidp->fid);
+
+ code = cm_Unlock(scp, LockType, LOffset, LLength, key, userp, &req);
+
+ if (code)
+ goto done;
+ }
+
+ op_locks = op;
+
+ for (i=0; i<NumberOfLocks; i++) {
+ smb_GetLockParams(LockType, &op, &pid, &LOffset, &LLength);
+
+ key = cm_GenerateKey(vcp->vcID, pid, fidp->fid);
+
+ code = cm_Lock(scp, LockType, LOffset, LLength, key, (Timeout != 0),
+ userp, &req, &lockp);
+
+ if (code == CM_ERROR_WOULDBLOCK && Timeout != 0) {
+ smb_waitingLock_t * wLock;
+
+ /* Put on waiting list */
+ if(wlRequest == NULL) {
+ int j;
+ char * opt;
+ cm_key_t tkey;
+ LARGE_INTEGER tOffset, tLength;
+
+ wlRequest = malloc(sizeof(smb_waitingLockRequest_t));
+
+ osi_assert(wlRequest != NULL);
+
+ wlRequest->vcp = vcp;
+ smb_HoldVC(vcp);
+ wlRequest->scp = scp;
+ cm_HoldSCache(scp);
+ wlRequest->inp = smb_CopyPacket(inp);
+ wlRequest->outp = smb_CopyPacket(outp);
+ wlRequest->lockType = LockType;
+ wlRequest->timeRemaining = Timeout;
+ wlRequest->locks = NULL;
+
+ /* The waiting lock request needs to have enough
+ information to undo all the locks in the request.
+ We do the following to store info about locks that
+ have already been granted. Sure, we can get most
+ of the info from the packet, but the packet doesn't
+ hold the result of cm_Lock call. In practice we
+ only receive packets with one or two locks, so we
+ are only wasting a few bytes here and there and
+ only for a limited period of time until the waiting
+ lock times out or is freed. */
+
+ for(opt = op_locks, j=i; j > 0; j--) {
+ smb_GetLockParams(LockType, &opt, &pid, &tOffset, &tLength);
+
+ tkey = cm_GenerateKey(vcp->vcID, pid, fidp->fid);
+
+ wLock = malloc(sizeof(smb_waitingLock_t));
+
+ osi_assert(wLock != NULL);
+
+ wLock->key = tkey;
+ wLock->LOffset = tOffset;
+ wLock->LLength = tLength;
+ wLock->lockp = NULL;
+ wLock->state = SMB_WAITINGLOCKSTATE_DONE;
+ osi_QAdd((osi_queue_t **) &wlRequest->locks,
+ &wLock->q);
+ }
+ }
+
+ wLock = malloc(sizeof(smb_waitingLock_t));
+
+ osi_assert(wLock != NULL);
+
+ wLock->key = key;
+ wLock->LOffset = LOffset;
+ wLock->LLength = LLength;
+ wLock->lockp = lockp;
+ wLock->state = SMB_WAITINGLOCKSTATE_WAITING;
+ osi_QAdd((osi_queue_t **) &wlRequest->locks,
+ &wLock->q);
+
+ osi_Log1(smb_logp, "smb_ReceiveV3Locking WaitingLock created 0x%x",
+ (long) wLock);
+
+ code = 0;
+ continue;
+ }
+
+ if (code) {
+ osi_Log1(smb_logp, "smb_ReceiveV3Locking cm_Lock failure code 0x%x", code);
+ break;
+ }
+ }
+
+ if (code) {
+
+ /* Since something went wrong with the lock number i, we now
+ have to go ahead and release any locks acquired before the
+ failure. All locks before lock number i (of which there
+ are i of them) have either been successful or are waiting.
+ Either case requires calling cm_Unlock(). */
+
+ /* And purge the waiting lock */
+ if(wlRequest != NULL) {
+ smb_waitingLock_t * wl;
+ smb_waitingLock_t * wlNext;
+ long ul_code;
+
+ for(wl = wlRequest->locks; wl; wl = wlNext) {
+
+ wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
+
+ ul_code = cm_Unlock(scp, LockType, wl->LOffset, wl->LLength, wl->key, userp, &req);
+
+ if(ul_code != 0) {
+ osi_Log1(smb_logp, "smb_ReceiveV3Locking cm_Unlock returns code %d", ul_code);
+ } else {
+ osi_Log0(smb_logp, "smb_ReceiveV3Locking cm_Unlock successful");
+ }
+
+ osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
+ free(wl);
+
+ }
+
+ smb_ReleaseVC(wlRequest->vcp);
+ cm_ReleaseSCache(wlRequest->scp);
+ smb_FreePacket(wlRequest->inp);
+ smb_FreePacket(wlRequest->outp);
+
+ free(wlRequest);
+
+ wlRequest = NULL;
+ }
+
+ } else {
+
+ if (wlRequest != NULL) {
+
+ lock_ObtainWrite(&smb_globalLock);
+ osi_QAdd((osi_queue_t **)&smb_allWaitingLocks,
+ &wlRequest->q);
+ osi_Wakeup((long) &smb_allWaitingLocks);
+ lock_ReleaseWrite(&smb_globalLock);
+
+ /* don't send reply immediately */
+ outp->flags |= SMB_PACKETFLAG_NOSEND;
+ }
+
+ smb_SetSMBDataLength(outp, 0);
+ }
+
+ done:
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
+
+ doneSync:
+ lock_ReleaseMutex(&scp->mx);
+ cm_ReleaseUser(userp);
+ smb_ReleaseFID(fidp);
+
+ return code;
}
long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- unsigned short fid;
+ unsigned short fid;
smb_fid_t *fidp;
cm_scache_t *scp;
long code = 0;
- time_t searchTime;
+ afs_uint32 searchTime;
cm_user_t *userp;
- cm_req_t req;
+ cm_req_t req;
- cm_InitReq(&req);
+ cm_InitReq(&req);
fid = smb_GetSMBParm(inp, 0);
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
- return CM_ERROR_BADFD;
+ return CM_ERROR_BADFD;
}
userp = smb_GetUser(vcp, inp);
scp = fidp->scp;
/* otherwise, stat the file */
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainMutex(&scp->mx);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code) goto done;
+ if (code) goto done;
- /* decode times. We need a search time, but the response to this
+ /* decode times. We need a search time, but the response to this
* 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);
+ smb_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 */
smb_SetSMBParm(outp, 8, scp->length.LowPart & 0xffff); /* alloc size */
smb_SetSMBParm(outp, 9, (scp->length.LowPart >> 16) & 0xffff);
- /* file attribute */
+ /* file attribute */
smb_SetSMBParm(outp, 10, smb_Attributes(scp));
/* and finalize stuff */
code = 0;
done:
- lock_ReleaseMutex(&scp->mx);
- cm_ReleaseUser(userp);
- smb_ReleaseFID(fidp);
- return code;
-}
+ lock_ReleaseMutex(&scp->mx);
+ cm_ReleaseUser(userp);
+ smb_ReleaseFID(fidp);
+ return code;
+}
long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- unsigned short fid;
+ unsigned short fid;
smb_fid_t *fidp;
cm_scache_t *scp;
long code = 0;
- time_t searchTime;
+ afs_uint32 searchTime;
time_t unixTime;
cm_user_t *userp;
cm_attr_t attrs;
- cm_req_t req;
+ cm_req_t req;
- cm_InitReq(&req);
+ cm_InitReq(&req);
fid = smb_GetSMBParm(inp, 0);
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
- return CM_ERROR_BADFD;
+ return CM_ERROR_BADFD;
}
userp = smb_GetUser(vcp, inp);
scp = fidp->scp;
- /* now prepare to call cm_setattr. This message only sets various times,
+ /* 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);
+ searchTime = smb_GetSMBParm(inp, 5) | (smb_GetSMBParm(inp, 6) << 16);
if (searchTime != 0) {
- smb_UnixTimeFromSearchTime(&unixTime, searchTime);
+ smb_UnixTimeFromSearchTime(&unixTime, searchTime);
if ( unixTime != -1 ) {
attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
}
else code = 0;
- cm_ReleaseUser(userp);
- smb_ReleaseFID(fidp);
- return code;
+ cm_ReleaseUser(userp);
+ smb_ReleaseFID(fidp);
+ return code;
}
long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- osi_hyper_t offset;
- long count, finalCount;
+ osi_hyper_t offset;
+ long count;
+ long finalCount = 0;
unsigned short fd;
+ unsigned pid;
smb_fid_t *fidp;
long code = 0;
cm_user_t *userp;
+ cm_key_t key;
char *op;
fd = smb_GetSMBParm(inp, 2);
osi_Log3(smb_logp, "smb_ReceiveV3Read fd %d, off 0x%x, size 0x%x",
fd, offset.LowPart, count);
- fd = smb_ChainFID(fd, inp);
+ fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
if (!fidp) {
- return CM_ERROR_BADFD;
+ return CM_ERROR_BADFD;
+ }
+
+ pid = ((smb_t *) inp)->pid;
+ key = cm_GenerateKey(vcp->vcID, pid, fd);
+ {
+ LARGE_INTEGER LOffset, LLength;
+
+ LOffset.HighPart = offset.HighPart;
+ LOffset.LowPart = offset.LowPart;
+ LLength.HighPart = 0;
+ LLength.LowPart = count;
+
+ lock_ObtainMutex(&fidp->scp->mx);
+ code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
+ lock_ReleaseMutex(&fidp->scp->mx);
+ }
+
+ if (code) {
+ smb_ReleaseFID(fidp);
+ return code;
}
- /* set inp->fid so that later read calls in same msg can find fid */
+
+ /* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fd;
if (fidp->flags & SMB_FID_IOCTL) {
- return smb_IoctlV3Read(fidp, vcp, inp, outp);
+ return smb_IoctlV3Read(fidp, vcp, inp, outp);
}
-
- userp = smb_GetUser(vcp, inp);
- /* 0 and 1 are reserved for request chaining, were setup by our caller,
+ userp = smb_GetUser(vcp, inp);
+
+ /* 0 and 1 are reserved for request chaining, were setup by our caller,
* and will be further filled in after we return.
*/
smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */
smb_SetSMBParm(outp, 3, 0); /* resvd */
smb_SetSMBParm(outp, 4, 0); /* resvd */
- smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
+ smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
/* fill in #6 when we have all the parameters' space reserved */
smb_SetSMBParm(outp, 7, 0); /* resv'd */
smb_SetSMBParm(outp, 8, 0); /* resv'd */
smb_SetSMBParm(outp, 9, 0); /* resv'd */
smb_SetSMBParm(outp, 10, 0); /* resv'd */
- smb_SetSMBParm(outp, 11, 0); /* reserved */
+ smb_SetSMBParm(outp, 11, 0); /* reserved */
- /* get op ptr after putting in the parms, since otherwise we don't
+ /* get op ptr after putting in the parms, since otherwise we don't
* 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)));
- /* set the packet data length the count of the # of bytes */
+ /* set the packet data length the count of the # of bytes */
smb_SetSMBDataLength(outp, count);
#ifndef DJGPP
- code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
+ code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
#else /* DJGPP */
- code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount, FALSE);
+ code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount, FALSE);
#endif /* !DJGPP */
- /* fix some things up */
- smb_SetSMBParm(outp, 5, finalCount);
- smb_SetSMBDataLength(outp, finalCount);
+ /* fix some things up */
+ smb_SetSMBParm(outp, 5, finalCount);
+ smb_SetSMBDataLength(outp, finalCount);
smb_ReleaseFID(fidp);
#define FILE_OVERWRITE 4 // (open & truncate, but do not create)
#define FILE_OVERWRITE_IF 5 // (open & truncate, or create)
+/* Flags field */
+#define REQUEST_OPLOCK 2
+#define REQUEST_BATCH_OPLOCK 4
+#define OPEN_DIRECTORY 8
+#define EXTENDED_RESPONSE_REQUIRED 0x10
+
+/* CreateOptions field. */
+#define FILE_DIRECTORY_FILE 0x0001
+#define FILE_WRITE_THROUGH 0x0002
+#define FILE_SEQUENTIAL_ONLY 0x0004
+#define FILE_NON_DIRECTORY_FILE 0x0040
+#define FILE_NO_EA_KNOWLEDGE 0x0200
+#define FILE_EIGHT_DOT_THREE_ONLY 0x0400
+#define FILE_RANDOM_ACCESS 0x0800
+#define FILE_DELETE_ON_CLOSE 0x1000
+#define FILE_OPEN_BY_FILE_ID 0x2000
+
long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
char *pathp, *realPathp;
unsigned int requestOpLock;
unsigned int requestBatchOpLock;
unsigned int mustBeDir;
+ unsigned int extendedRespRequired;
unsigned int treeCreate;
int realDirFlag;
unsigned int desiredAccess;
unsigned int extAttributes;
unsigned int createDisp;
unsigned int createOptions;
+ unsigned int shareAccess;
int initialModeBits;
unsigned short baseFid;
smb_fid_t *baseFidp;
cm_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
+ * we don't lose a reference. Start by ensuring that they are NULL.
+ */
+ scp = NULL;
+ dscp = NULL;
treeCreate = FALSE;
foundscp = FALSE;
- scp = NULL;
nameLength = smb_GetSMBOffsetParm(inp, 2, 1);
flags = smb_GetSMBOffsetParm(inp, 3, 1)
| (smb_GetSMBOffsetParm(inp, 4, 1) << 16);
- requestOpLock = flags & 0x02;
- requestBatchOpLock = flags & 0x04;
- mustBeDir = flags & 0x08;
+ requestOpLock = flags & REQUEST_OPLOCK;
+ requestBatchOpLock = flags & REQUEST_BATCH_OPLOCK;
+ mustBeDir = flags & OPEN_DIRECTORY;
+ extendedRespRequired = flags & EXTENDED_RESPONSE_REQUIRED;
/*
* Why all of a sudden 32-bit FID?
| (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
extAttributes = smb_GetSMBOffsetParm(inp, 13, 1)
| (smb_GetSMBOffsetParm(inp, 14, 1) << 16);
+ shareAccess = smb_GetSMBOffsetParm(inp, 15, 1)
+ | (smb_GetSMBOffsetParm(inp, 16, 1) << 16);
createDisp = smb_GetSMBOffsetParm(inp, 17, 1)
| (smb_GetSMBOffsetParm(inp, 18, 1) << 16);
createOptions = smb_GetSMBOffsetParm(inp, 19, 1)
/* mustBeDir is never set; createOptions directory bit seems to be
* more important
*/
- if (createOptions & 1)
+ if (createOptions & FILE_DIRECTORY_FILE)
realDirFlag = 1;
- else if (createOptions & 0x40)
+ else if (createOptions & FILE_NON_DIRECTORY_FILE)
realDirFlag = 0;
else
realDirFlag = -1;
* extended attributes
*/
initialModeBits = 0666;
- if (extAttributes & 1)
+ if (extAttributes & SMB_ATTR_READONLY)
initialModeBits &= ~0222;
pathp = smb_GetSMBData(inp, NULL);
realPathp = malloc(nameLength+1);
memcpy(realPathp, pathp, nameLength);
realPathp[nameLength] = 0;
+ if (smb_StoreAnsiFilenames)
+ OemToChar(realPathp,realPathp);
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, realPathp);
osi_Log1(smb_logp,"NTCreateX for [%s]",osi_LogSaveString(smb_logp,realPathp));
osi_Log4(smb_logp,"... da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
- osi_Log2(smb_logp,"... flags=[%x] lastNamep=[%s]", flags, osi_LogSaveString(smb_logp,(lastNamep?lastNamep:"null")));
+ osi_Log3(smb_logp,"... share=[%x] flags=[%x] lastNamep=[%s]", shareAccess, flags, osi_LogSaveString(smb_logp,(lastNamep?lastNamep:"null")));
if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
/* special case magic file name for receiving IOCTL requests
free(hexp);
}
#endif
+
userp = smb_GetUser(vcp, inp);
if (!userp) {
osi_Log1(smb_logp, "NTCreateX Invalid user [%d]", ((smb_t *) inp)->uid);
}
if (baseFid == 0) {
- baseDirp = cm_rootSCachep;
+ baseDirp = cm_data.rootSCachep;
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if (code == CM_ERROR_TIDIPC) {
/* Attempt to use a TID allocated for IPC. The client
* is probably looking for DCE RPC end points which we
- * don't support. */
+ * don't support OR it could be looking to make a DFS
+ * referral request.
+ */
osi_Log0(smb_logp, "NTCreateX received IPC TID");
+#ifndef DFS_SUPPORT
free(realPathp);
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHFILE;
+#endif /* DFS_SUPPORT */
}
- }
- else {
+ } else {
baseFidp = smb_FindFID(vcp, baseFid, 0);
if (!baseFidp) {
osi_Log1(smb_logp, "NTCreateX Invalid base fid [%d]", baseFid);
fidflags |= SMB_FID_OPENREAD;
if (desiredAccess & AFS_ACCESS_WRITE)
fidflags |= SMB_FID_OPENWRITE;
+ if (createOptions & FILE_DELETE_ON_CLOSE)
+ fidflags |= SMB_FID_DELONCLOSE;
+
+ /* and the share mode */
+ if (shareAccess & FILE_SHARE_READ)
+ fidflags |= SMB_FID_SHARE_READ;
+ if (shareAccess & FILE_SHARE_WRITE)
+ fidflags |= SMB_FID_SHARE_WRITE;
- dscp = NULL;
code = 0;
+
/* For an exclusive create, we want to do a case sensitive match for the last component. */
if ( createDisp == FILE_CREATE ||
createDisp == FILE_OVERWRITE ||
code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
if (code == 0) {
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
userp, &req, &scp);
if (code == CM_ERROR_NOSUCHFILE) {
return CM_ERROR_EXISTS;
}
}
- } else
- dscp = NULL;
+ }
+ /* we have both scp and dscp */
} else {
code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
+#ifdef DFS_SUPPORT
+ if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+ /* we might have scp but not dscp */
}
- if (code == 0)
- foundscp = TRUE;
+ 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*
* recognize.
*/
- if ( !dscp ) {
- while (1) {
+ /* we might or might not have scp */
+
+ if (dscp == NULL) {
+ do {
char *tp;
code = cm_NameI(baseDirp, spacep->data,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
+#ifdef DFS_SUPPORT
+ if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ if (scp)
+ cm_ReleaseSCache(scp);
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
+
if (code &&
(tp = strrchr(spacep->data,'\\')) &&
(createDisp == FILE_CREATE) &&
smb_ReleaseFID(baseFidp);
cm_ReleaseUser(userp);
free(realPathp);
+ if (scp)
+ cm_ReleaseSCache(scp);
return CM_ERROR_BADNTFILENAME;
}
+ code = 0;
}
- else
- break;
- }
+ } while (dscp == NULL && code == 0);
} else
code = 0;
+ /* we might have scp and we might have dscp */
+
if (baseFid != 0)
- smb_ReleaseFID(baseFidp);
+ smb_ReleaseFID(baseFidp);
if (code) {
osi_Log0(smb_logp,"NTCreateX parent not found");
+ if (scp)
+ cm_ReleaseSCache(scp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
if (treeCreate && dscp->fileType == CM_SCACHETYPE_FILE) {
/* A file exists where we want a directory. */
+ if (scp)
+ cm_ReleaseSCache(scp);
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
lastNamep++;
if (!smb_IsLegalFilename(lastNamep)) {
- cm_ReleaseSCache(dscp);
+ if (scp)
+ cm_ReleaseSCache(scp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_BADNTFILENAME;
if (!foundscp && !treeCreate) {
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);
- } else {
- code = cm_Lookup(dscp, lastNamep,
- CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
- userp, &req, &scp);
- }
+ } else {
+ code = cm_Lookup(dscp, lastNamep,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+ userp, &req, &scp);
+ }
if (code && code != CM_ERROR_NOSUCHFILE) {
- cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
}
}
- }
- else {
+ /* we have scp and dscp */
+ } else {
+ /* we have scp but not dscp */
if (baseFid != 0)
smb_ReleaseFID(baseFidp);
- }
-
- /* 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,
- * scp is NULL.
- */
- if (code == 0 && !treeCreate) {
- if (createDisp == FILE_CREATE) {
- /* oops, file shouldn't be there */
- if (dscp) cm_ReleaseSCache(dscp);
+ }
+
+ /* 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,
+ * scp is NULL.
+ */
+ if (code == 0 && !treeCreate) {
+ if (createDisp == FILE_CREATE) {
+ /* oops, file shouldn't be there */
+ if (dscp)
+ cm_ReleaseSCache(dscp);
+ if (scp)
cm_ReleaseSCache(scp);
- cm_ReleaseUser(userp);
- free(realPathp);
- return CM_ERROR_EXISTS;
- }
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ return CM_ERROR_EXISTS;
+ }
- if ( createDisp == FILE_OVERWRITE ||
- createDisp == FILE_OVERWRITE_IF) {
- setAttr.mask = CM_ATTRMASK_LENGTH;
- setAttr.length.LowPart = 0;
- setAttr.length.HighPart = 0;
- /* now watch for a symlink */
- code = 0;
- while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
- targetScp = 0;
- code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
- if (code == 0) {
- /* we have a more accurate file to use (the
- * target of the symbolic link). Otherwise,
- * we'll just use the symlink anyway.
- */
- osi_Log2(smb_logp, "symlink vp %x to vp %x",
- scp, targetScp);
- cm_ReleaseSCache(scp);
- scp = targetScp;
- }
+ if ( createDisp == FILE_OVERWRITE ||
+ createDisp == FILE_OVERWRITE_IF) {
+
+ setAttr.mask = CM_ATTRMASK_LENGTH;
+ setAttr.length.LowPart = 0;
+ setAttr.length.HighPart = 0;
+ /* now watch for a symlink */
+ code = 0;
+ while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
+ targetScp = 0;
+ osi_assert(dscp != NULL);
+ code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
+ if (code == 0) {
+ /* we have a more accurate file to use (the
+ * target of the symbolic link). Otherwise,
+ * we'll just use the symlink anyway.
+ */
+ osi_Log2(smb_logp, "symlink vp %x to vp %x",
+ scp, targetScp);
+ cm_ReleaseSCache(scp);
+ scp = targetScp;
}
- code = cm_SetAttr(scp, &setAttr, userp, &req);
- openAction = 3; /* truncated existing file */
}
- else
- openAction = 1; /* found existing file */
+ code = cm_SetAttr(scp, &setAttr, userp, &req);
+ openAction = 3; /* truncated existing file */
+ }
+ else
+ openAction = 1; /* found existing file */
- code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
- &req);
- if (code) {
- if (dscp) cm_ReleaseSCache(dscp);
+ code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req);
+ if (code) {
+ if (dscp)
+ cm_ReleaseSCache(dscp);
+ if (scp)
cm_ReleaseSCache(scp);
- cm_ReleaseUser(userp);
- free(realPathp);
- return code;
- }
- }
- else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
- /* don't create if not found */
- if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
- return CM_ERROR_NOSUCHFILE;
- }
- else if (realDirFlag == 0 || realDirFlag == -1) {
- osi_assert(dscp != NULL);
- osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s",
- osi_LogSaveString(smb_logp, lastNamep));
- openAction = 2; /* created file */
- setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
- setAttr.clientModTime = time(NULL);
- code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
- &req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+ return code;
+ }
+ } else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
+ /* don't create if not found */
+ if (dscp)
+ cm_ReleaseSCache(dscp);
+ if (scp)
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ return CM_ERROR_NOSUCHFILE;
+ } else if (realDirFlag == 0 || realDirFlag == -1) {
+ osi_assert(dscp != NULL);
+ osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s",
+ osi_LogSaveString(smb_logp, lastNamep));
+ openAction = 2; /* created file */
+ setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
+ setAttr.clientModTime = time(NULL);
+ code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, &req);
+ if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+ smb_NotifyChange(FILE_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ dscp, lastNamep, NULL, TRUE);
+ if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
+ /* Not an exclusive create, and someone else tried
+ * creating it already, then we open it anyway. We
+ * don't bother retrying after this, since if this next
+ * fails, that means that the file was deleted after we
+ * started this call.
+ */
+ code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
+ userp, &req, &scp);
+ if (code == 0) {
+ if (createDisp == FILE_OVERWRITE_IF) {
+ setAttr.mask = CM_ATTRMASK_LENGTH;
+ setAttr.length.LowPart = 0;
+ setAttr.length.HighPart = 0;
+
+ /* now watch for a symlink */
+ code = 0;
+ while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
+ targetScp = 0;
+ code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
+ if (code == 0) {
+ /* we have a more accurate file to use (the
+ * target of the symbolic link). Otherwise,
+ * we'll just use the symlink anyway.
+ */
+ osi_Log2(smb_logp, "symlink vp %x to vp %x",
+ scp, targetScp);
+ cm_ReleaseSCache(scp);
+ scp = targetScp;
+ }
+ }
+ code = cm_SetAttr(scp, &setAttr, userp, &req);
+ }
+ } /* lookup succeeded */
+ }
+ } else {
+ char *tp, *pp;
+ char *cp; /* This component */
+ int clen = 0; /* length of component */
+ cm_scache_t *tscp1, *tscp2;
+ int isLast = 0;
+
+ /* create directory */
+ if ( !treeCreate )
+ treeStartp = lastNamep;
+ osi_assert(dscp != NULL);
+ osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]",
+ osi_LogSaveString(smb_logp, treeStartp));
+ openAction = 2; /* created directory */
+
+ setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
+ setAttr.clientModTime = time(NULL);
+
+ pp = treeStartp;
+ cp = spacep->data;
+ tscp1 = dscp;
+ cm_HoldSCache(tscp1);
+ tscp2 = NULL;
+
+ while (pp && *pp) {
+ tp = strchr(pp, '\\');
+ if (!tp) {
+ strcpy(cp,pp);
+ clen = strlen(cp);
+ isLast = 1; /* indicate last component. the supplied path never ends in a slash */
+ } else {
+ clen = tp - pp;
+ strncpy(cp,pp,clen);
+ *(cp + clen) = 0;
+ tp++;
+ }
+ pp = tp;
+
+ if (clen == 0)
+ continue; /* the supplied path can't have consecutive slashes either , but */
+
+ /* cp is the next component to be created. */
+ code = cm_MakeDir(tscp1, cp, 0, &setAttr, userp, &req);
+ if (code == 0 && (tscp1->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- dscp, lastNamep, NULL, TRUE);
- if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ tscp1, cp, NULL, TRUE);
+ if (code == 0 ||
+ (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE)) {
/* Not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
* fails, that means that the file was deleted after we
* started this call.
*/
- code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
- userp, &req, &scp);
- if (code == 0) {
- if (createDisp == FILE_OVERWRITE_IF) {
- setAttr.mask = CM_ATTRMASK_LENGTH;
- setAttr.length.LowPart = 0;
- setAttr.length.HighPart = 0;
-
- /* now watch for a symlink */
- code = 0;
- while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
- targetScp = 0;
- code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
- if (code == 0) {
- /* we have a more accurate file to use (the
- * target of the symbolic link). Otherwise,
- * we'll just use the symlink anyway.
- */
- osi_Log2(smb_logp, "symlink vp %x to vp %x",
- scp, targetScp);
- cm_ReleaseSCache(scp);
- scp = targetScp;
- }
- }
- code = cm_SetAttr(scp, &setAttr, userp, &req);
- }
- } /* lookup succeeded */
- }
- }
- else {
- char *tp, *pp;
- char *cp; /* This component */
- int clen = 0; /* length of component */
- cm_scache_t *tscp;
- int isLast = 0;
-
- /* create directory */
- if ( !treeCreate )
- treeStartp = lastNamep;
- osi_assert(dscp != NULL);
- osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]",
- osi_LogSaveString(smb_logp, treeStartp));
- openAction = 2; /* created directory */
-
- setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
- setAttr.clientModTime = time(NULL);
-
- pp = treeStartp;
- cp = spacep->data;
- tscp = dscp;
-
- while (pp && *pp) {
- tp = strchr(pp, '\\');
- if (!tp) {
- strcpy(cp,pp);
- clen = strlen(cp);
- isLast = 1; /* indicate last component. the supplied path never ends in a slash */
- }
- else {
- clen = tp - pp;
- strncpy(cp,pp,clen);
- *(cp + clen) = 0;
- tp++;
- }
- pp = tp;
-
- if (clen == 0)
- continue; /* the supplied path can't have consecutive slashes either , but */
-
- /* cp is the next component to be created. */
- code = cm_MakeDir(tscp, cp, 0, &setAttr, userp, &req);
- if (code == 0 && (tscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_DIR_NAME,
- tscp, cp, NULL, TRUE);
- if (code == 0 ||
- (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE)) {
- /* Not an exclusive create, and someone else tried
- * creating it already, then we open it anyway. We
- * don't bother retrying after this, since if this next
- * fails, that means that the file was deleted after we
- * started this call.
- */
- code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD,
- userp, &req, &scp);
- }
- if (code) break;
+ code = cm_Lookup(tscp1, cp, CM_FLAG_CASEFOLD,
+ userp, &req, &tscp2);
+ }
+ if (code)
+ break;
- if (!isLast) { /* for anything other than dscp, release it unless it's the last one */
- cm_ReleaseSCache(tscp);
- tscp = scp; /* Newly created directory will be next parent */
- }
+ if (!isLast) { /* for anything other than dscp, release it unless it's the last one */
+ cm_ReleaseSCache(tscp1);
+ tscp1 = tscp2; /* Newly created directory will be next parent */
+ /* the hold is transfered to tscp1 from tscp2 */
}
+ }
- /*
- * if we get here and code == 0, then scp is the last directory created, and tscp is the
- * parent of scp. dscp got released if dscp != tscp. both tscp and scp are held.
- */
- dscp = tscp;
- }
+ if (dscp)
+ cm_ReleaseSCache(dscp);
+ dscp = tscp1;
+ 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.
+ */
+ }
if (code) {
/* something went wrong creating or truncating the file */
- if (scp) cm_ReleaseSCache(scp);
- if (dscp) cm_ReleaseSCache(dscp);
+ if (scp)
+ cm_ReleaseSCache(scp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
* target of the symbolic link). Otherwise,
* we'll just use the symlink anyway.
*/
- osi_Log2(smb_logp, "symlink vp %x to vp %x",
- scp, targetScp);
+ osi_Log2(smb_logp, "symlink vp %x to vp %x", scp, targetScp);
cm_ReleaseSCache(scp);
scp = targetScp;
}
}
if (scp->fileType != CM_SCACHETYPE_FILE) {
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
/* (only applies to single component case) */
if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
cm_ReleaseSCache(scp);
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_NOTDIR;
/* open the file itself */
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
osi_assert(fidp);
+
+ /* If we are restricting sharing, we should do so with a suitable
+ share lock. */
+ if (scp->fileType == CM_SCACHETYPE_FILE &&
+ !(fidflags & SMB_FID_SHARE_WRITE)) {
+ cm_key_t key;
+ LARGE_INTEGER LOffset, LLength;
+ int sLockType;
+
+ LOffset.HighPart = SMB_FID_QLOCK_HIGH;
+ LOffset.LowPart = SMB_FID_QLOCK_LOW;
+ LLength.HighPart = 0;
+ LLength.LowPart = SMB_FID_QLOCK_LENGTH;
+
+ if (fidflags & SMB_FID_SHARE_READ) {
+ sLockType = LOCKING_ANDX_SHARED_LOCK;
+ } else {
+ sLockType = 0;
+ }
+
+ key = cm_GenerateKey(vcp->vcID, SMB_FID_QLOCK_PID, fidp->fid);
+
+ lock_ObtainMutex(&scp->mx);
+ code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
+ lock_ReleaseMutex(&scp->mx);
+
+ if (code) {
+ fidp->flags = SMB_FID_DELETE;
+ smb_ReleaseFID(fidp);
+
+ cm_ReleaseSCache(scp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+
+ return CM_ERROR_SHARING_VIOLATION;
+ }
+ }
+
/* save a pointer to the vnode */
- fidp->scp = scp;
+ fidp->scp = scp; /* Hold transfered to fidp->scp and no longer needed */
fidp->flags = fidflags;
fidp->NTopen_wholepathp = realPathp;
/* we don't need this any longer */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp) {
+ cm_ReleaseSCache(dscp);
+ dscp = NULL;
+ }
+
cm_Open(scp, 0, userp);
/* set inp->fid so that later read calls in same msg can find fid */
cm_ReleaseUser(userp);
- /* Can't free realPathp if we get here since fidp->NTopen_wholepathp is pointing there */
+ /* Can't free realPathp if we get here since
+ fidp->NTopen_wholepathp is pointing there */
/* leave scp held since we put it in fidp->scp */
return 0;
unsigned int desiredAccess;
#ifdef DEBUG_VERBOSE
unsigned int allocSize;
- unsigned int shareAccess;
#endif
+ unsigned int shareAccess;
unsigned int extAttributes;
unsigned int createDisp;
#ifdef DEBUG_VERBOSE
lparmp = (ULONG *) parmp;
flags = lparmp[0];
- requestOpLock = flags & 0x02;
- requestBatchOpLock = flags & 0x04;
- mustBeDir = flags & 0x08;
- extendedRespRequired = flags & 0x10;
+ requestOpLock = flags & REQUEST_OPLOCK;
+ requestBatchOpLock = flags & REQUEST_BATCH_OPLOCK;
+ mustBeDir = flags & OPEN_DIRECTORY;
+ extendedRespRequired = flags & EXTENDED_RESPONSE_REQUIRED;
/*
* Why all of a sudden 32-bit FID?
allocSize = lparmp[3];
#endif /* DEBUG_VERSOSE */
extAttributes = lparmp[5];
-#ifdef DEBUG_VEROSE
shareAccess = lparmp[6];
-#endif
createDisp = lparmp[7];
createOptions = lparmp[8];
#ifdef DEBUG_VERBOSE
/* mustBeDir is never set; createOptions directory bit seems to be
* more important
*/
- if (createOptions & 1)
+ if (createOptions & FILE_DIRECTORY_FILE)
realDirFlag = 1;
- else if (createOptions & 0x40)
+ else if (createOptions & FILE_NON_DIRECTORY_FILE)
realDirFlag = 0;
else
realDirFlag = -1;
realPathp = malloc(nameLength+1);
memcpy(realPathp, pathp, nameLength);
realPathp[nameLength] = 0;
+ if (smb_StoreAnsiFilenames)
+ OemToChar(realPathp,realPathp);
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->data, &lastNamep, realPathp);
}
if (baseFid == 0) {
- baseDirp = cm_rootSCachep;
+ baseDirp = cm_data.rootSCachep;
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
- if(code == CM_ERROR_TIDIPC) {
- /* Attempt to use TID allocated for IPC. The client is
- * probably trying to locate DCE RPC endpoints, which we
- * don't support. */
+ if (code == CM_ERROR_TIDIPC) {
+ /* Attempt to use a TID allocated for IPC. The client
+ * is probably looking for DCE RPC end points which we
+ * don't support OR it could be looking to make a DFS
+ * referral request.
+ */
osi_Log0(smb_logp, "NTTranCreate received IPC TID");
+#ifndef DFS_SUPPORT
free(realPathp);
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
+#endif
}
- }
- else {
+ } else {
baseFidp = smb_FindFID(vcp, baseFid, 0);
if (!baseFidp) {
osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
fidflags |= SMB_FID_OPENREAD;
if (desiredAccess & AFS_ACCESS_WRITE)
fidflags |= SMB_FID_OPENWRITE;
+ if (createOptions & FILE_DELETE_ON_CLOSE)
+ fidflags |= SMB_FID_DELONCLOSE;
+
+ /* And the share mode */
+ if (shareAccess & FILE_SHARE_READ)
+ fidflags |= SMB_FID_SHARE_READ;
+ if (shareAccess & FILE_SHARE_WRITE)
+ fidflags |= SMB_FID_SHARE_WRITE;
dscp = NULL;
code = 0;
code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
if (code == 0) {
+#ifdef DFS_SUPPORT
+ if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
userp, &req, &scp);
if (code == CM_ERROR_NOSUCHFILE) {
} else {
code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
+#ifdef DFS_SUPPORT
+ if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
}
if (code == 0)
foundscp = TRUE;
- if (code != 0
- || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
+
+ if (code != 0 || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
/* look up parent directory */
if ( !dscp ) {
code = cm_NameI(baseDirp, spacep->data,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &dscp);
+#ifdef DFS_SUPPORT
+ if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ if ( WANTS_DFS_PATHNAMES(inp) )
+ return CM_ERROR_PATH_NOT_COVERED;
+ else
+ return CM_ERROR_BADSHARENAME;
+ }
+#endif /* DFS_SUPPORT */
} else
code = 0;
return code;
}
}
- }
- else {
+ } else {
if (baseFid != 0) {
smb_ReleaseFID(baseFidp);
baseFidp = 0;
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
&req);
if (code) {
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
}
else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
/* don't create if not found */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_NOSUCHFILE;
}
} /* lookup succeeded */
}
- }
- else {
+ } else {
/* create directory */
osi_assert(dscp != NULL);
osi_Log1(smb_logp,
if (code) {
/* something went wrong creating or truncating the file */
- if (scp) cm_ReleaseSCache(scp);
+ if (scp)
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
osi_assert(fidp);
+ /* If we are restricting sharing, we should do so with a suitable
+ share lock. */
+ if (scp->fileType == CM_SCACHETYPE_FILE &&
+ !(fidflags & SMB_FID_SHARE_WRITE)) {
+ cm_key_t key;
+ LARGE_INTEGER LOffset, LLength;
+ int sLockType;
+
+ LOffset.HighPart = SMB_FID_QLOCK_HIGH;
+ LOffset.LowPart = SMB_FID_QLOCK_LOW;
+ LLength.HighPart = 0;
+ LLength.LowPart = SMB_FID_QLOCK_LENGTH;
+
+ if (fidflags & SMB_FID_SHARE_READ) {
+ sLockType = LOCKING_ANDX_SHARED_LOCK;
+ } else {
+ sLockType = 0;
+ }
+
+ key = cm_GenerateKey(vcp->vcID, SMB_FID_QLOCK_PID, fidp->fid);
+
+ lock_ObtainMutex(&scp->mx);
+ code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
+ lock_ReleaseMutex(&scp->mx);
+
+ if (code) {
+ fidp->flags = SMB_FID_DELETE;
+ smb_ReleaseFID(fidp);
+
+ cm_ReleaseSCache(scp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+
+ return CM_ERROR_SHARING_VIOLATION;
+ }
+ }
+
/* save a pointer to the vnode */
fidp->scp = scp;
fidp->NTopen_wholepathp = realPathp;
/* we don't need this any longer */
- if (dscp) cm_ReleaseSCache(dscp);
+ if (dscp)
+ cm_ReleaseSCache(dscp);
cm_Open(scp, 0, userp);
long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
smb_packet_t *outp)
{
- smb_packet_t *savedPacketp;
- ULONG filter; USHORT fid, watchtree;
- smb_fid_t *fidp;
- cm_scache_t *scp;
+ smb_packet_t *savedPacketp;
+ 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);
- watchtree = smb_GetSMBParm(inp, 22) && 0xffff; /* TODO: should this be 0xff ? */
+ filter = smb_GetSMBParm(inp, 19) |
+ (smb_GetSMBParm(inp, 20) << 16);
+ fid = smb_GetSMBParm(inp, 21);
+ watchtree = smb_GetSMBParm(inp, 22) && 0xffff; /* TODO: should this be 0xff ? */
fidp = smb_FindFID(vcp, fid, 0);
if (!fidp) {
return CM_ERROR_BADFD;
}
- savedPacketp = smb_CopyPacket(inp);
+ savedPacketp = smb_CopyPacket(inp);
smb_HoldVC(vcp);
- savedPacketp->vcp = vcp;
- lock_ObtainMutex(&smb_Dir_Watch_Lock);
- savedPacketp->nextp = smb_Directory_Watches;
- smb_Directory_Watches = savedPacketp;
- lock_ReleaseMutex(&smb_Dir_Watch_Lock);
+ savedPacketp->vcp = vcp;
+ lock_ObtainMutex(&smb_Dir_Watch_Lock);
+ savedPacketp->nextp = smb_Directory_Watches;
+ smb_Directory_Watches = savedPacketp;
+ lock_ReleaseMutex(&smb_Dir_Watch_Lock);
osi_Log4(smb_logp, "Request for NotifyChange filter 0x%x fid %d wtree %d file %s",
filter, fid, watchtree, osi_LogSaveString(smb_logp, fidp->NTopen_wholepathp));
lock_ReleaseMutex(&scp->mx);
smb_ReleaseFID(fidp);
- outp->flags |= SMB_PACKETFLAG_NOSEND;
- return 0;
+ outp->flags |= SMB_PACKETFLAG_NOSEND;
+ return 0;
}
unsigned char nullSecurityDesc[36] = {
- 0x01, /* security descriptor revision */
- 0x00, /* reserved, should be zero */
- 0x00, 0x80, /* security descriptor control;
- * 0x8000 : self-relative format */
- 0x14, 0x00, 0x00, 0x00, /* offset of owner SID */
- 0x1c, 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, /* security descriptor revision */
+ 0x00, /* reserved, should be zero */
+ 0x00, 0x80, /* security descriptor control;
+ * 0x8000 : self-relative format */
+ 0x14, 0x00, 0x00, 0x00, /* offset of owner SID */
+ 0x1c, 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 */
+};
long smb_ReceiveNTTranQuerySecurityDesc(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- int parmOffset, parmCount, dataOffset, dataCount;
- int parmSlot;
- int maxData;
- char *outData;
- char *parmp;
- USHORT *sparmp;
- ULONG *lparmp;
- USHORT fid;
- ULONG securityInformation;
-
- parmOffset = smb_GetSMBOffsetParm(inp, 11, 1)
- | (smb_GetSMBOffsetParm(inp, 12, 1) << 16);
- parmp = inp->data + parmOffset;
- sparmp = (USHORT *) parmp;
- lparmp = (ULONG *) parmp;
-
- fid = sparmp[0];
- securityInformation = lparmp[1];
-
- maxData = smb_GetSMBOffsetParm(inp, 7, 1)
- | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
-
- if (maxData < 36)
- dataCount = 0;
- else
- dataCount = 36;
-
- /* 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;
- /* Total Data Count */
- smb_SetSMBParmLong(outp, parmSlot, dataCount); parmSlot += 2;
- /* Parameter Count */
- smb_SetSMBParmLong(outp, parmSlot, parmCount); parmSlot += 2;
- /* Parameter Offset */
- smb_SetSMBParmLong(outp, parmSlot, parmOffset); 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;
- /* Data Displacement */
- smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
- smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
- smb_SetSMBDataLength(outp, 1 + parmCount + dataCount);
-
- outData = smb_GetSMBData(outp, NULL);
- outData++; /* round to get to parmOffset */
- *((ULONG *)outData) = 36; outData += 4; /* length */
-
- if (maxData >= 36) {
- memcpy(outData, nullSecurityDesc, 36);
- outData += 36;
- return 0;
- } else
- return CM_ERROR_BUFFERTOOSMALL;
+ int parmOffset, parmCount, dataOffset, dataCount;
+ int parmSlot;
+ int maxData;
+ char *outData;
+ char *parmp;
+ USHORT *sparmp;
+ ULONG *lparmp;
+ USHORT fid;
+ ULONG securityInformation;
+
+ parmOffset = smb_GetSMBOffsetParm(inp, 11, 1)
+ | (smb_GetSMBOffsetParm(inp, 12, 1) << 16);
+ parmp = inp->data + parmOffset;
+ sparmp = (USHORT *) parmp;
+ lparmp = (ULONG *) parmp;
+
+ fid = sparmp[0];
+ securityInformation = lparmp[1];
+
+ maxData = smb_GetSMBOffsetParm(inp, 7, 1)
+ | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
+
+ if (maxData < 36)
+ dataCount = 0;
+ else
+ dataCount = 36;
+
+ /* 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;
+ /* Total Data Count */
+ smb_SetSMBParmLong(outp, parmSlot, dataCount); parmSlot += 2;
+ /* Parameter Count */
+ smb_SetSMBParmLong(outp, parmSlot, parmCount); parmSlot += 2;
+ /* Parameter Offset */
+ smb_SetSMBParmLong(outp, parmSlot, parmOffset); 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;
+ /* Data Displacement */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
+ smb_SetSMBDataLength(outp, 1 + parmCount + dataCount);
+
+ outData = smb_GetSMBData(outp, NULL);
+ outData++; /* round to get to parmOffset */
+ *((ULONG *)outData) = 36; outData += 4; /* length */
+
+ if (maxData >= 36) {
+ memcpy(outData, nullSecurityDesc, 36);
+ outData += 36;
+ return 0;
+ } else
+ return CM_ERROR_BUFFERTOOSMALL;
}
long smb_ReceiveNTTransact(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
/* We can handle long names */
if (vcp->flags & SMB_VCFLAG_USENT)
- ((smb_t *)outp)->flg2 |= 0x40; /* IS_LONG_NAME */
+ ((smb_t *)outp)->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
switch (function) {
case 6:
lock_ReleaseMutex(&dscp->mx);
/* Convert to response packet */
- ((smb_t *) watch)->reb = 0x80;
+ ((smb_t *) watch)->reb = SMB_FLAGS_SERVER_TO_CLIENT | SMB_FLAGS_CANONICAL_PATHNAMES;
((smb_t *) watch)->wct = 0;
/* out parms */
smb_SetSMBDataLength(watch, parmCount + 1);
if (parmCount != 0) {
+ char * p;
outData = smb_GetSMBData(watch, NULL);
outData++; /* round to get to parmOffset */
oldOutData = outData;
/* Action */
*((DWORD *)outData) = nameLen*2; outData += 4;
/* File Name Length */
- mbstowcs((WCHAR *)outData, filename, nameLen);
+ p = strdup(filename);
+ if (smb_StoreAnsiFilenames)
+ CharToOem(p,p);
+ mbstowcs((WCHAR *)outData, p, nameLen);
+ free(p);
/* File Name */
if (twoEntries) {
outData = oldOutData + oldParmCount;
/* Action */
*((DWORD *)outData) = otherNameLen*2;
outData += 4; /* File Name Length */
- mbstowcs((WCHAR *)outData, otherFilename,
- otherNameLen); /* File Name */
+ p = strdup(otherFilename);
+ if (smb_StoreAnsiFilenames)
+ CharToOem(p,p);
+ mbstowcs((WCHAR *)outData, p, otherNameLen); /* File Name */
+ free(p);
}
}
((smb_t *) watch)->errLow = 0;
((smb_t *) watch)->errHigh = 0;
/* Set NT Status codes flag */
- ((smb_t *) watch)->flg2 |= 0x4000;
+ ((smb_t *) watch)->flg2 |= SMB_FLAGS2_32BIT_STATUS;
}
smb_SendPacket(vcp, watch);
- smb_ReleaseVC(vcp);
smb_FreePacket(watch);
watch = nextWatch;
}
((smb_t *)watch)->reh = 0x1;
((smb_t *)watch)->errLow = 0;
((smb_t *)watch)->errHigh = 0xC0;
- ((smb_t *)watch)->flg2 |= 0x4000;
+ ((smb_t *)watch)->flg2 |= SMB_FLAGS2_32BIT_STATUS;
smb_SendPacket(vcp, watch);
- if (watch->vcp)
- smb_ReleaseVC(watch->vcp);
smb_FreePacket(watch);
return 0;
}
long smb_ReceiveNTRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- char *oldname, *newname;
+ char *oldPathp, *newPathp;
long code = 0;
- cm_user_t *userp;
char * tp;
int attrs;
int rename_type;
}
tp = smb_GetSMBData(inp, NULL);
- oldname = smb_ParseASCIIBlock(tp, &tp);
- newname = smb_ParseASCIIBlock(tp, &tp);
+ oldPathp = smb_ParseASCIIBlock(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(oldPathp,oldPathp);
+ newPathp = smb_ParseASCIIBlock(tp, &tp);
+ if (smb_StoreAnsiFilenames)
+ OemToChar(newPathp,newPathp);
osi_Log3(smb_logp, "NTRename for [%s]->[%s] type [%s]",
- osi_LogSaveString(smb_logp, oldname),
- osi_LogSaveString(smb_logp, newname),
+ osi_LogSaveString(smb_logp, oldPathp),
+ osi_LogSaveString(smb_logp, newPathp),
((rename_type==RENAME_FLAG_RENAME)?"rename":"hardlink"));
if (rename_type == RENAME_FLAG_RENAME) {
- code = smb_Rename(vcp,inp,oldname,newname,attrs);
+ code = smb_Rename(vcp,inp,oldPathp,newPathp,attrs);
} else { /* RENAME_FLAG_HARD_LINK */
- code = smb_Link(vcp,inp,oldname,newname);
+ code = smb_Link(vcp,inp,oldPathp,newPathp);
}
return code;
}
lock_ObtainMutex(&unp->mx);
unp->userp = cm_NewUser();
lock_ReleaseMutex(&unp->mx);
- osi_Log2(smb_logp,"smb_FindCMUserByName New user name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
+ osi_Log2(smb_logp,"smb_FindCMUserByName New user name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
osi_LogEvent("AFS smb_FindCMUserByName : New User",NULL,"name[%s] machine[%s]",usern,machine);
} else {
osi_Log2(smb_logp,"smb_FindCMUserByName Not found name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));