Windows: Kill AFS_LARGEFILES preprocessor symbol
[openafs.git] / src / WINNT / afsd / smb3.c
index 14edcec..9811d3f 100644 (file)
@@ -16,6 +16,7 @@
 #include <ntstatus.h>
 #define SECURITY_WIN32
 #include <security.h>
+#include <sddl.h>
 #include <lmaccess.h>
 #pragma warning(pop)
 #include <stdlib.h>
@@ -115,10 +116,10 @@ unsigned long smb_ExtAttributes(cm_scache_t *scp)
      * turns out to be impolitic in NT.  See defect 10007.
      */
 #ifdef notdef
-    if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+    if ((scp->unixModeBits & 0200) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
         attrs |= SMB_ATTR_READONLY;            /* Read-only */
 #else
-    if ((scp->unixModeBits & 0222) == 0)
+    if ((scp->unixModeBits & 0200) == 0)
         attrs |= SMB_ATTR_READONLY;            /* Read-only */
 #endif
 
@@ -263,6 +264,149 @@ void smb_NegotiateExtendedSecurity(void ** secBlob, int * secBlobLength) {
     return;
 }
 
+afs_uint32
+smb_GetLogonSID(HANDLE hToken, PSID *ppsid)
+{
+    BOOL bSuccess = FALSE;
+    DWORD dwIndex;
+    DWORD dwLength = 0;
+    PTOKEN_GROUPS ptg = NULL;
+
+    // Verify the parameter passed in is not NULL.
+    if (NULL == ppsid)
+        goto Cleanup;
+
+    // Get required buffer size and allocate the TOKEN_GROUPS buffer.
+
+    if (!GetTokenInformation( hToken,         // handle to the access token
+                              TokenGroups,    // get information about the token's groups
+                              (LPVOID) ptg,   // pointer to TOKEN_GROUPS buffer
+                              0,              // size of buffer
+                              &dwLength       // receives required buffer size
+                              ))
+    {
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+            goto Cleanup;
+
+        ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),
+                                        HEAP_ZERO_MEMORY, dwLength);
+
+        if (ptg == NULL)
+            goto Cleanup;
+    }
+
+    // Get the token group information from the access token.
+
+    if (!GetTokenInformation( hToken,         // handle to the access token
+                              TokenGroups,    // get information about the token's groups
+                              (LPVOID) ptg,   // pointer to TOKEN_GROUPS buffer
+                              dwLength,       // size of buffer
+                              &dwLength       // receives required buffer size
+                              ))
+    {
+        goto Cleanup;
+    }
+
+    // Loop through the groups to find the logon SID.
+    for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) {
+        if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) ==  SE_GROUP_LOGON_ID)
+        {
+            // Found the logon SID; make a copy of it.
+
+            dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid);
+            *ppsid = (PSID) HeapAlloc(GetProcessHeap(),
+                                       HEAP_ZERO_MEMORY, dwLength);
+            if (*ppsid == NULL)
+                goto Cleanup;
+            if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid))
+            {
+                HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
+                goto Cleanup;
+            }
+            bSuccess = TRUE;
+            break;
+        }
+    }
+
+  Cleanup:
+
+    // Free the buffer for the token groups.
+    if (ptg != NULL)
+        HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
+
+    return bSuccess;
+}
+
+afs_uint32
+smb_GetUserSID(HANDLE hToken, PSID *ppsid)
+{
+    BOOL bSuccess = FALSE;
+    DWORD dwLength = 0;
+    PTOKEN_USER ptu = NULL;
+
+    // Verify the parameter passed in is not NULL.
+    if (NULL == ppsid)
+        goto Cleanup;
+
+    // Get required buffer size and allocate the TOKEN_USER buffer.
+
+    if (!GetTokenInformation( hToken,         // handle to the access token
+                              TokenUser,      // get information about the token's user
+                              (LPVOID) ptu,   // pointer to TOKEN_USER buffer
+                              0,              // size of buffer
+                              &dwLength       // receives required buffer size
+                              ))
+    {
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+            goto Cleanup;
+
+        ptu = (PTOKEN_USER)HeapAlloc(GetProcessHeap(),
+                                        HEAP_ZERO_MEMORY, dwLength);
+
+        if (ptu == NULL)
+            goto Cleanup;
+    }
+
+    // Get the token group information from the access token.
+
+    if (!GetTokenInformation( hToken,         // handle to the access token
+                              TokenUser,      // get information about the token's user
+                              (LPVOID) ptu,   // pointer to TOKEN_USER buffer
+                              dwLength,       // size of buffer
+                              &dwLength       // receives required buffer size
+                              ))
+    {
+        goto Cleanup;
+    }
+
+    // Found the user SID; make a copy of it.
+    dwLength = GetLengthSid(ptu->User.Sid);
+    *ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
+    if (*ppsid == NULL)
+        goto Cleanup;
+    if (!CopySid(dwLength, *ppsid, ptu->User.Sid))
+    {
+        HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
+        goto Cleanup;
+    }
+    bSuccess = TRUE;
+
+  Cleanup:
+
+    // Free the buffer for the token groups.
+    if (ptu != NULL)
+        HeapFree(GetProcessHeap(), 0, (LPVOID)ptu);
+
+    return bSuccess;
+}
+
+void
+smb_FreeSID (PSID psid)
+{
+    HeapFree(GetProcessHeap(), 0, (LPVOID)psid);
+}
+
+
 struct smb_ext_context {
     CredHandle creds;
     CtxtHandle ctx;
@@ -272,7 +416,8 @@ struct smb_ext_context {
 
 long smb_AuthenticateUserExt(smb_vc_t * vcp, clientchar_t * usern,
                              char * secBlobIn, int secBlobInLength,
-                             char ** secBlobOut, int * secBlobOutLength) {
+                             char ** secBlobOut, int * secBlobOutLength,
+                             wchar_t **secSidString) {
     SECURITY_STATUS status, istatus;
     CredHandle creds;
     TimeStamp expiry;
@@ -292,6 +437,7 @@ long smb_AuthenticateUserExt(smb_vc_t * vcp, clientchar_t * usern,
 
     *secBlobOut = NULL;
     *secBlobOutLength = 0;
+    *secSidString = NULL;
 
     if (vcp->flags & SMB_VCFLAG_AUTH_IN_PROGRESS) {
         secCtx = vcp->secCtx;
@@ -427,6 +573,7 @@ long smb_AuthenticateUserExt(smb_vc_t * vcp, clientchar_t * usern,
 
     if (status == SEC_E_OK || status == SEC_I_COMPLETE_NEEDED) {
         /* woo hoo! */
+        HANDLE hToken = 0;
         SecPkgContext_NamesW names;
 
         OutputDebugF(_C("Authentication completed"));
@@ -442,6 +589,21 @@ long smb_AuthenticateUserExt(smb_vc_t * vcp, clientchar_t * usern,
             OutputDebugF(_C("QueryContextAttributes Names failed [%x]"), GetLastError());
             code = CM_ERROR_BADPASSWORD; 
         }
+
+        /* Obtain the user's SID */
+        if (code == 0 && !QuerySecurityContextToken(((secCtx)?&ctx:NULL), &hToken)) {
+            PSID pSid = 0;
+            OutputDebugF(_C("Received hToken"));
+
+            if (smb_GetUserSID(hToken, &pSid))
+                ConvertSidToStringSidW(pSid, secSidString);
+
+            if (pSid)
+                smb_FreeSID(pSid);
+            CloseHandle(hToken);
+        } else {
+            OutputDebugF(_C("QueryContextToken failed [%x]"), GetLastError());
+        }
     } else if (!code) {
         switch ( status ) {
         case SEC_E_INVALID_TOKEN:
@@ -679,8 +841,10 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     clientchar_t *s1 = _C(" ");
     long code = 0; 
     clientchar_t usern[SMB_MAX_USERNAME_LENGTH];
+    int usernIsSID = 0;
     char *secBlobOut = NULL;
     int  secBlobOutLength = 0;
+    wchar_t *secSidString = 0;
     int  maxBufferSize = 0;
     int  maxMpxCount = 0;
     int  vcNumber = 0;
@@ -729,7 +893,7 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
             secBlobInLength = smb_GetSMBParm(inp, 7);
             secBlobIn = smb_GetSMBData(inp, NULL);
 
-            code = smb_AuthenticateUserExt(vcp, usern, secBlobIn, secBlobInLength, &secBlobOut, &secBlobOutLength);
+            code = smb_AuthenticateUserExt(vcp, usern, secBlobIn, secBlobInLength, &secBlobOut, &secBlobOutLength, &secSidString);
 
             if (code == CM_ERROR_GSSCONTINUE) {
                 size_t cb_data = 0;
@@ -875,9 +1039,20 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
        early to avoid accidently stealing someone else's tokens. */
 
     if (code) {
+        if (secSidString)
+            LocalFree(secSidString);
         return code;
     }
 
+    /*
+     * If the SidString for the user could be obtained, use that
+     * for the user id
+     */
+    if (secSidString) {
+        cm_ClientStrCpy(usern, SMB_MAX_USERNAME_LENGTH, secSidString);
+        usernIsSID = 1;
+    }
+
     OutputDebugF(_C("Received username=[%s]"), usern);
 
     /* On Windows 2000, this function appears to be called more often than
@@ -909,6 +1084,8 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
             */
            unp->flags &= ~SMB_USERNAMEFLAG_AFSLOGON;
        }
+    if (usernIsSID)
+        unp->flags |= SMB_USERNAMEFLAG_SID;
        lock_ReleaseMutex(&unp->mx);
 
         /* Create a new UID and cm_user_t structure */
@@ -986,6 +1163,8 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         }
     }
 
+    if (secSidString)
+        LocalFree(secSidString);
     return 0;
 }
 
@@ -1445,9 +1624,11 @@ long smb_nmpipeSetState(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     osi_Log2(smb_logp, "smb_nmpipeSetState for fd[%d] with state[0x%x]", fd, pipeState);
 
     fidp = smb_FindFID(vcp, fd, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "smb_nmpipeSetState Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
        return CM_ERROR_BADFD;
-
+    }
     lock_ObtainMutex(&fidp->mx);
     if (pipeState & 0x8000)
        fidp->flags |= SMB_FID_BLOCKINGPIPE;
@@ -1478,9 +1659,11 @@ long smb_nmpipeTransact(smb_vc_t * vcp, smb_tran2Packet_t *p, smb_packet_t *op)
             fd, p->totalData, p->maxReturnData);
 
     fidp = smb_FindFID(vcp, fd, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "smb_nmpipeTransact Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
        return CM_ERROR_BADFD;
-
+    }
     lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_RPC) {
        is_rpc = 1;
@@ -1492,6 +1675,8 @@ long smb_nmpipeTransact(smb_vc_t * vcp, smb_tran2Packet_t *p, smb_packet_t *op)
        smb_ReleaseFID(fidp);
     } else {
        /* We only deal with RPC pipes */
+        osi_Log2(smb_logp, "smb_nmpipeTransact Not a RPC vcp 0x%p fid %d",
+                 vcp, fd);
        code = CM_ERROR_BADFD;
     }
 
@@ -1787,6 +1972,7 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_
     cm_req_t req;
     cm_user_t * userp;
     osi_hyper_t thyper;
+    cm_scache_t *rootScp;
 
     tp = p->parmsp + 1; /* skip over function number (always 0) */
 
@@ -1856,9 +2042,10 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_
     thyper.HighPart = 0;
     thyper.LowPart = 0;
 
-    cm_HoldSCache(cm_data.rootSCachep);
-    cm_ApplyDir(cm_data.rootSCachep, smb_rapCollectSharesProc, &rootShares, &thyper, userp, &req, NULL);
-    cm_ReleaseSCache(cm_data.rootSCachep);
+    rootScp = cm_RootSCachep(userp, &req);
+    cm_HoldSCache(rootScp);
+    cm_ApplyDir(rootScp, smb_rapCollectSharesProc, &rootShares, &thyper, userp, &req, NULL);
+    cm_ReleaseSCache(rootScp);
 
     cm_ReleaseUser(userp);
 
@@ -2028,7 +2215,7 @@ long smb_ReceiveRAPNetShareGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pack
             osi_Log1(smb_logp,"ReceiveRAPNetShareGetInfo unable to resolve user [%d]", p->uid);
             return CM_ERROR_BADSMB;
         }   
-        code = cm_NameI(cm_data.rootSCachep, shareName,
+        code = cm_NameI(cm_RootSCachep(userp, &req), shareName,
                          CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
                          userp, NULL, &req, &scp);
         if (code == 0) {
@@ -2474,7 +2661,6 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     cm_scache_t *dscp;         /* dir we're dealing with */
     cm_scache_t *scp;          /* file we're creating */
     cm_attr_t setAttr;
-    int initialModeBits;
     smb_fid_t *fidp;
     int attributes;
     clientchar_t *lastNamep;
@@ -2508,11 +2694,6 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     attributes = p->parmsp[3];
     dosTime = p->parmsp[4] | (p->parmsp[5] << 16);
         
-    /* compute initial mode bits based on read-only flag in attributes */
-    initialModeBits = 0666;
-    if (attributes & SMB_ATTR_READONLY) 
-        initialModeBits &= ~0222;
-        
     pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[14]), NULL,
                                   SMB_STRF_ANSIPATH);
     
@@ -2596,7 +2777,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 
 #ifndef DFS_SUPPORT
     if (is_ipc) {
-        osi_Log0(smb_logp, "Tran2Open rejecting IPC TID");
+        osi_Log1(smb_logp, "Tran2Open rejecting IPC TID vcp %p", vcp);
        smb_FreeTran2Packet(outp);
        return CM_ERROR_BADFD;
     }
@@ -2637,13 +2818,16 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     }
 
     dscp = NULL;
-    code = cm_NameI(cm_data.rootSCachep, pathp,
+    code = cm_NameI(cm_RootSCachep(userp, &req), pathp,
                      CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                      userp, tidPathp, &req, &scp);
     if (code != 0) {
-        code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
-                         CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                         userp, tidPathp, &req, &dscp);
+        if (code == CM_ERROR_NOSUCHFILE ||
+            code == CM_ERROR_NOSUCHPATH ||
+            code == CM_ERROR_BPLUS_NOMATCH)
+            code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
+                            CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                            userp, tidPathp, &req, &dscp);
         cm_FreeSpace(spacep);
 
         if (code) {
@@ -2748,6 +2932,8 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
         openAction = 2;        /* created file */
         setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
         cm_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
+        smb_SetInitialModeBitsForFile(attributes, &setAttr);
+
         code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
                           &req);
         if (code == 0) {
@@ -3074,7 +3260,7 @@ long cm_GetShortName(clientchar_t *pathp, cm_user_t *userp, cm_req_t *reqp,
     /* smb_StripLastComponent will strip "::$DATA" if present */
     smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
 
-    code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+    code = cm_NameI(cm_RootSCachep(userp, reqp), spacep->wdata,
                     caseFold, userp, tidPathp,
                     reqp, &dscp);
     cm_FreeSpace(spacep);
@@ -3168,7 +3354,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     memset(&qpi, 0, sizeof(qpi));
 
     pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[3]), NULL, SMB_STRF_ANSIPATH);
-    osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path %S", infoLevel,
+    osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path \"%S\"", infoLevel,
               osi_LogSaveClientString(smb_logp, pathp));
 
     outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, responseSize);
@@ -3197,12 +3383,16 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
     code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
     if(code) {
+        osi_Log1(smb_logp, "ReceiveTran2QPathInfo tid path lookup failure 0x%x", code);
         cm_ReleaseUser(userp);
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHPATH);
         smb_FreeTran2Packet(outp);
         return 0;
     }
 
+    osi_Log1(smb_logp, "T2 QPathInfo tidPathp \"%S\"",
+              osi_LogSaveClientString(smb_logp, tidPathp));
+
     /*
      * XXX Strange hack XXX
      *
@@ -3225,7 +3415,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         /* Make sure that lastComp is not NULL */
         if (lastComp) {
             if (cm_ClientStrCmpIA(lastComp,  _C("\\desktop.ini")) == 0) {
-                code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+                code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
                                  CM_FLAG_CASEFOLD
                                  | CM_FLAG_DIRSEARCH
                                  | CM_FLAG_FOLLOW,
@@ -3268,9 +3458,14 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         cm_FreeSpace(spacep);
     }
 
-    /* now do namei and stat, and copy out the info */
-    code = cm_NameI(cm_data.rootSCachep, pathp,
-                     CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
+    if (code == 0 ||
+        code == CM_ERROR_NOSUCHFILE ||
+        code == CM_ERROR_NOSUCHPATH ||
+        code == CM_ERROR_BPLUS_NOMATCH) {
+        /* now do namei and stat, and copy out the info */
+        code = cm_NameI(cm_RootSCachep(userp, &req), pathp,
+                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
+    }
 
     if (code) {
         cm_ReleaseUser(userp);
@@ -3550,7 +3745,7 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         /* Make sure that lastComp is not NULL */
         if (lastComp) {
             if (cm_ClientStrCmpI(lastComp,  _C("\\desktop.ini")) == 0) {
-                code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+                code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
                                  CM_FLAG_CASEFOLD
                                  | CM_FLAG_DIRSEARCH
                                  | CM_FLAG_FOLLOW,
@@ -3592,9 +3787,15 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         cm_FreeSpace(spacep);
     }
 
-    /* now do namei and stat, and copy out the info */
-    code = cm_NameI(cm_data.rootSCachep, pathp,
-                     CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
+    if (code == 0 ||
+        code == CM_ERROR_NOSUCHFILE ||
+        code == CM_ERROR_NOSUCHPATH ||
+        code == CM_ERROR_BPLUS_NOMATCH) {
+        /* now do namei and stat, and copy out the info */
+        code = cm_NameI(cm_RootSCachep(userp, &req), pathp,
+                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
+    }
+
     if (code) {
         cm_ReleaseUser(userp);
         smb_SendTran2Error(vcp, p, opx, code);
@@ -3634,13 +3835,13 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         }
                
         if (spi->u.QPstandardInfo.attributes != 0) {
-            if ((scp->unixModeBits & 0222)
+            if ((scp->unixModeBits & 0200)
                  && (spi->u.QPstandardInfo.attributes & SMB_ATTR_READONLY) != 0) {
                 /* make a writable file read-only */
                 attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
                 attr.unixModeBits = scp->unixModeBits & ~0222;
             }
-            else if ((scp->unixModeBits & 0222) == 0
+            else if ((scp->unixModeBits & 0200) == 0
                       && (spi->u.QPstandardInfo.attributes & SMB_ATTR_READONLY) == 0) {
                 /* make a read-only file writable */
                 attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
@@ -3697,6 +3898,8 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     fidp = smb_FindFID(vcp, fid, 0);
 
     if (fidp == NULL) {
+        osi_Log2(smb_logp, "Tran2QFileInfo Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
         return 0;
     }
@@ -3807,13 +4010,21 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     }
     else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO) {
         size_t len = 0;
-        /* For now we have no streams */
-        qfi.u.QFfileStreamInfo.nextEntryOffset = 0;
-        qfi.u.QFfileStreamInfo.streamSize = scp->length;
-        qfi.u.QFfileStreamInfo.streamAllocationSize = scp->length;
-        smb_UnparseString(opx, qfi.u.QFfileStreamInfo.fileName, L"::$DATA", &len, SMB_STRF_IGNORENUL);
-        qfi.u.QFfileStreamInfo.streamNameLength = len;
-        responseSize -= (sizeof(qfi.u.QFfileStreamInfo.fileName) - len);
+
+        if (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+            scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+            scp->fileType == CM_SCACHETYPE_INVALID) {
+            /* Do not return the alternate streams for directories */
+            responseSize = 0;
+        } else {
+            /* For now we have no alternate streams */
+            qfi.u.QFfileStreamInfo.nextEntryOffset = 0;
+            qfi.u.QFfileStreamInfo.streamSize = scp->length;
+            qfi.u.QFfileStreamInfo.streamAllocationSize = scp->length;
+            smb_UnparseString(opx, qfi.u.QFfileStreamInfo.fileName, L"::$DATA", &len, SMB_STRF_IGNORENUL);
+            qfi.u.QFfileStreamInfo.streamNameLength = len;
+            responseSize -= (sizeof(qfi.u.QFfileStreamInfo.fileName) - len);
+        }
     }
     outp->totalData = responseSize;
 
@@ -3856,6 +4067,8 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
     fidp = smb_FindFID(vcp, fid, 0);
 
     if (fidp == NULL) {
+        osi_Log2(smb_logp, "Tran2SetFileInfo Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
         return 0;
     }
@@ -3959,13 +4172,13 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                
         attribute = sfi->u.QFbasicInfo.attributes;
         if (attribute != 0) {
-            if ((scp->unixModeBits & 0222)
+            if ((scp->unixModeBits & 0200)
                  && (attribute & SMB_ATTR_READONLY) != 0) {
                 /* make a writable file read-only */
                 attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
                 attr.unixModeBits = scp->unixModeBits & ~0222;
             }
-            else if ((scp->unixModeBits & 0222) == 0
+            else if ((scp->unixModeBits & 0200) == 0
                       && (attribute & SMB_ATTR_READONLY) == 0) {
                 /* make a read-only file writable */
                 attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
@@ -4153,7 +4366,7 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
              * for might be a known name with the final character stripped
              * off.
              */
-            code = cm_NameI(cm_data.rootSCachep, &requestFileName[nbnLen+2],
+            code = cm_NameI(cm_RootSCachep(userp, &req), &requestFileName[nbnLen+2],
                             CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
                             userp, NULL, &req, &scp);
             if (code == 0 ||
@@ -4192,7 +4405,7 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                     /* smb_StripLastComponent will strip "::$DATA" if present */
                     smb_StripLastComponent(pathName, &lastComponent, temp);
 
-                    code = cm_NameI(cm_data.rootSCachep, pathName,
+                    code = cm_NameI(cm_RootSCachep(userp, &req), pathName,
                                     CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                                     userp, NULL, &req, &dscp);
                     if (code == 0) {
@@ -4226,7 +4439,7 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 *q = '\0';
                 
                 if (smb_FindShare(vcp, vcp->usersp, shareName, &p)) {
-                    code = cm_NameI(cm_data.rootSCachep, _C(""), 
+                    code = cm_NameI(cm_RootSCachep(userp, &req), _C(""),
                                     CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
                                     userp, p, &req, &scp);
                     free(p);
@@ -4804,7 +5017,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op
         return 0;
     }
 
-    code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+    code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
                     CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                     userp, tidPathp, &req, &scp);
     cm_FreeSpace(spacep);
@@ -5331,7 +5544,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         cm_ClientStrCpy(dsp->tidPath, lengthof(dsp->tidPath), tidPathp ? tidPathp : _C("/"));
         cm_ClientStrCpy(dsp->relPath, lengthof(dsp->relPath), spacep->wdata);
 
-        code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+        code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
                         CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &scp);
         cm_FreeSpace(spacep);
@@ -5906,7 +6119,6 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     cm_scache_t *dscp;         /* dir we're dealing with */
     cm_scache_t *scp;          /* file we're creating */
     cm_attr_t setAttr;
-    int initialModeBits;
     smb_fid_t *fidp;
     int attributes;
     clientchar_t *lastNamep;
@@ -5937,11 +6149,6 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     attributes = smb_GetSMBParm(inp, 5);
     dosTime = smb_GetSMBParm(inp, 6) | (smb_GetSMBParm(inp, 7) << 16);
 
-                                /* compute initial mode bits based on read-only flag in attributes */
-    initialModeBits = 0666;
-    if (attributes & SMB_ATTR_READONLY) 
-       initialModeBits &= ~0222;
-        
     pathp = smb_ParseASCIIBlock(inp, smb_GetSMBData(inp, NULL), NULL,
                                 SMB_STRF_ANSIPATH);
     if (!pathp)
@@ -6050,7 +6257,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     userp = smb_GetUserFromVCP(vcp, inp);
 
     dscp = NULL;
-    code = cm_NameI(cm_data.rootSCachep, pathp,
+    code = cm_NameI(cm_RootSCachep(userp, &req), pathp,
                     CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                     userp, tidPathp, &req, &scp);
 
@@ -6067,9 +6274,12 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 #endif /* DFS_SUPPORT */
 
     if (code != 0) {
-        code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
-                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                        userp, tidPathp, &req, &dscp);
+        if (code == CM_ERROR_NOSUCHFILE ||
+            code == CM_ERROR_NOSUCHPATH ||
+            code == CM_ERROR_BPLUS_NOMATCH)
+            code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
+                            CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                            userp, tidPathp, &req, &dscp);
         if (code) {
             cm_ReleaseUser(userp);
             return code;
@@ -6149,6 +6359,8 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         openAction = 2;        /* created file */
         setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
         smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
+        smb_SetInitialModeBitsForFile(attributes, &setAttr);
+
         code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
                          &req);
         if (code == 0) {
@@ -6313,9 +6525,11 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fid = smb_ChainFID(fid, inp);
 
     fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "V3LockingX Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
        return CM_ERROR_BADFD;
-    
+    }
     lock_ObtainMutex(&fidp->mx);
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
         lock_ReleaseMutex(&fidp->mx);
@@ -6430,7 +6644,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                            userp, &req, &lockp);
        }
 
-        if (code == CM_ERROR_WOULDBLOCK && Timeout != 0) {
+        if (code == CM_ERROR_LOCK_NOT_GRANTED && Timeout != 0) {
             smb_waitingLock_t * wLock;
 
             /* Put on waiting list */
@@ -6599,9 +6813,11 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     fid = smb_ChainFID(fid, inp);
         
     fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "V3GetAttributes Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
        return CM_ERROR_BADFD;
-    
+    }
     lock_ObtainMutex(&fidp->mx);
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
         lock_ReleaseMutex(&fidp->mx);
@@ -6690,9 +6906,11 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     fid = smb_ChainFID(fid, inp);
         
     fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "V3SetAttributes Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
        return CM_ERROR_BADFD;
-    
+    }
     lock_ObtainMutex(&fidp->mx);
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
         lock_ReleaseMutex(&fidp->mx);
@@ -6764,17 +6982,7 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     if (*inp->wctp == 14) {
         /* we have a request with 64-bit file offsets */
-#ifdef AFS_LARGEFILES
         offset.HighPart = smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16);
-#else
-        if ((smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16)) != 0) {
-            /* uh oh */
-            osi_Log0(smb_logp, "smb_ReceiveV3WriteX offset requires largefile support");
-            /* we shouldn't have received this op if we didn't specify
-               largefile support */
-            return CM_ERROR_INVAL;
-        }
-#endif
     }
 
     op = inp->data + smb_GetSMBParm(inp, 11);
@@ -6785,9 +6993,11 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "smb_ReceiveV3WriteX Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
         return CM_ERROR_BADFD;
-        
+    }
     lock_ObtainMutex(&fidp->mx);
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
         lock_ReleaseMutex(&fidp->mx);
@@ -6860,8 +7070,10 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
      */
     lock_ObtainMutex(&fidp->mx);
     if ((fidp->flags & SMB_FID_MTIMESETDONE) != SMB_FID_MTIMESETDONE) {
+        lock_ObtainWrite(&fidp->scp->rw);
         scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
         scp->clientModTime = time(NULL);
+        lock_ReleaseWrite(&fidp->scp->rw);
     }
     lock_ReleaseMutex(&fidp->mx);
 
@@ -6917,7 +7129,6 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     if (*inp->wctp == 12) {
         /* a request with 64-bit offsets */
-#ifdef AFS_LARGEFILES
         offset.HighPart = smb_GetSMBParm(inp, 10) | (smb_GetSMBParm(inp, 11) << 16);
 
         if (LargeIntegerLessThanZero(offset)) {
@@ -6925,14 +7136,6 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                      offset.HighPart, offset.LowPart);
             return CM_ERROR_BADSMB;
         }
-#else
-        if ((smb_GetSMBParm(inp, 10) | (smb_GetSMBParm(inp, 11) << 16)) != 0) {
-            osi_Log0(smb_logp, "smb_ReceiveV3Read offset is 64-bit.  Dropping");
-            return CM_ERROR_BADSMB;
-        } else {
-            offset.HighPart = 0;
-        }
-#endif
     } else {
         offset.HighPart = 0;
     }
@@ -6943,6 +7146,8 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
     if (!fidp) {
+        osi_Log2(smb_logp, "smb_ReceiveV3Read Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
         return CM_ERROR_BADFD;
     }
 
@@ -7103,7 +7308,6 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     unsigned int createDisp;
     unsigned int createOptions;
     unsigned int shareAccess;
-    int initialModeBits;
     unsigned short baseFid;
     smb_fid_t *baseFidp;
     smb_fid_t *fidp;
@@ -7170,14 +7374,6 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     else
         realDirFlag = -1;
 
-    /*
-     * compute initial mode bits based on read-only flag in
-     * extended attributes
-     */
-    initialModeBits = 0666;
-    if (extAttributes & SMB_ATTR_READONLY) 
-        initialModeBits &= ~0222;
-
     pathp = smb_ParseStringCb(inp, smb_GetSMBData(inp, NULL), nameLength,
                               NULL, SMB_STRF_ANSIPATH);
 
@@ -7196,7 +7392,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     if (baseFid == 0) {
        baseFidp = NULL;
-        baseDirp = cm_data.rootSCachep;
+        baseDirp = cm_RootSCachep(cm_rootUserp, &req);
         code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
         if (code == CM_ERROR_TIDIPC) {
             /* Attempt to use a TID allocated for IPC.  The client
@@ -7380,13 +7576,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                     cm_ReleaseSCache(dscp);
                     cm_ReleaseUser(userp);
                     free(realPathp);
-                   if (baseFidp) 
+                   if (baseFidp)
                        smb_ReleaseFID(baseFidp);
                     return CM_ERROR_EXISTS;
                 }
             }
+            /* we have both scp and dscp */
         }
-        /* we have both scp and dscp */
     } else {
         code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &scp);
@@ -7407,6 +7603,17 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         /* we might have scp but not dscp */
     }
 
+    if (code &&
+        code != CM_ERROR_NOSUCHFILE &&
+        code != CM_ERROR_NOSUCHPATH &&
+        code != CM_ERROR_BPLUS_NOMATCH) {
+        cm_ReleaseUser(userp);
+        free(realPathp);
+        if (baseFidp)
+            smb_ReleaseFID(baseFidp);
+        return code;
+    }
+
     if (scp)
         foundscp = TRUE;
     
@@ -7446,6 +7653,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 #endif /* DFS_SUPPORT */
 
                 if (code &&
+                    (code == CM_ERROR_NOSUCHFILE ||
+                     code == CM_ERROR_NOSUCHPATH ||
+                     code == CM_ERROR_BPLUS_NOMATCH) &&
                     (tp = cm_ClientStrRChr(spacep->wdata, '\\')) &&
                     (createDisp == FILE_CREATE) &&
                     (realDirFlag == 1)) {
@@ -7624,6 +7834,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         openAction = 2;                /* created file */
         setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
         setAttr.clientModTime = time(NULL);
+        smb_SetInitialModeBitsForFile(extAttributes, &setAttr);
+
         code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, &req);
         if (code == 0) {
            created = 1;
@@ -7690,6 +7902,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
         setAttr.clientModTime = time(NULL);
+        smb_SetInitialModeBitsForDir(extAttributes, &setAttr);
 
         pp = treeStartp;
         cp = spacep->wdata;
@@ -7862,7 +8075,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
            smb_CloseFID(vcp, fidp, NULL, 0);
            smb_ReleaseFID(fidp);
             free(realPathp);
-            return code;
+            return CM_ERROR_SHARING_VIOLATION;
         }
     }
 
@@ -8034,7 +8247,6 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     unsigned int impLevel;
     unsigned int secFlags;
     unsigned int createOptions;
-    int initialModeBits;
     unsigned short baseFid;
     smb_fid_t *baseFidp;
     smb_fid_t *fidp;
@@ -8100,14 +8312,6 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     else
         realDirFlag = -1;
 
-    /*
-     * compute initial mode bits based on read-only flag in
-     * extended attributes
-     */
-    initialModeBits = 0666;
-    if (extAttributes & SMB_ATTR_READONLY) 
-        initialModeBits &= ~0222;
-
     pathp = smb_ParseStringCb(inp, (parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR)),
                                nameLength, NULL, SMB_STRF_ANSIPATH);
     /* Sometimes path is not nul-terminated, so we make a copy. */
@@ -8153,7 +8357,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 
     if (baseFid == 0) {
        baseFidp = NULL;
-        baseDirp = cm_data.rootSCachep;
+        baseDirp = cm_RootSCachep(cm_rootUserp, &req);
         code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
         if (code == CM_ERROR_TIDIPC) {
             /* Attempt to use a TID allocated for IPC.  The client
@@ -8171,7 +8375,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     } else {
         baseFidp = smb_FindFID(vcp, baseFid, 0);
         if (!baseFidp) {
-           osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
+            osi_Log2(smb_logp, "NTTranCreate Unknown SMB Fid vcp 0x%p fid %d",
+                      vcp, baseFid);
             free(realPathp);
             cm_ReleaseUser(userp);
             return CM_ERROR_BADFD;
@@ -8251,8 +8456,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                     return CM_ERROR_EXISTS;
                 }
             }
-        } else 
-            dscp = NULL;
+        }
     } else {
         code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                         userp, tidPathp, &req, &scp);
@@ -8275,7 +8479,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     if (code == 0) 
         foundscp = TRUE;
 
-    if (code != 0 || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
+    if (code == CM_ERROR_NOSUCHFILE ||
+        code == CM_ERROR_NOSUCHPATH ||
+        code == CM_ERROR_BPLUS_NOMATCH ||
+        (code == 0 && (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)))) {
         /* look up parent directory */
         if ( !dscp ) {
             code = cm_NameI(baseDirp, spacep->wdata,
@@ -8422,6 +8629,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         openAction = 2;                /* created file */
         setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
         setAttr.clientModTime = time(NULL);
+        smb_SetInitialModeBitsForFile(extAttributes, &setAttr);
+
         code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
                           &req);
         if (code == 0) {
@@ -8474,6 +8683,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         openAction = 2;                /* created directory */
         setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
         setAttr.clientModTime = time(NULL);
+        smb_SetInitialModeBitsForDir(extAttributes, &setAttr);
+
         code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req, NULL);
         if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
             smb_NotifyChange(FILE_ACTION_ADDED,
@@ -8780,7 +8991,8 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
 
     fidp = smb_FindFID(vcp, fid, 0);
     if (!fidp) {
-        osi_Log1(smb_logp, "ERROR: NotifyChange given invalid fid [%d]", fid);
+        osi_Log2(smb_logp, "NotifyChange Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
         return CM_ERROR_BADFD;
     }
 
@@ -8854,88 +9066,180 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
     return 0;
 }
 
-unsigned char nullSecurityDesc[36] = {
+unsigned char nullSecurityDesc[] = {
     0x01,                              /* security descriptor revision */
     0x00,                              /* reserved, should be zero */
-    0x00, 0x80,                                /* security descriptor control;
-                                         * 0x8000 : self-relative format */
+    0x04, 0x80,                                /* security descriptor control;
+                                         * 0x0004 : null-DACL present - everyone has full access
+                                         * 0x8000 : relative format */
     0x14, 0x00, 0x00, 0x00,            /* offset of owner SID */
-    0x1c, 0x00, 0x00, 0x00,            /* offset of group SID */
+    0x20, 0x00, 0x00, 0x00,            /* offset of group SID */
     0x00, 0x00, 0x00, 0x00,            /* offset of DACL would go here */
     0x00, 0x00, 0x00, 0x00,            /* offset of SACL would go here */
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                        /* "null SID" owner SID */
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-                                        /* "null SID" group SID */
+    0x01, 0x01, 0x00, 0x00,             /* "everyone SID" owner SID */
+    0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x00,
+    0x01, 0x01, 0x00, 0x00,             /* "everyone SID" owner SID */
+    0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x00
 };      
 
 /* NT_TRANSACT_QUERY_SECURITY_DESC (SMB_COM_NT_TRANSACT) */
 long smb_ReceiveNTTranQuerySecurityDesc(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     int parmOffset, parmCount, dataOffset, dataCount;
+    int totalParmCount, totalDataCount;
     int parmSlot;
-    int maxData;
+    int maxData, maxParm;
+    int inTotalParm, inTotalData;
+    int inParm, inData;
+    int inParmOffset, inDataOffset;
     char *outData;
     char *parmp;
     USHORT *sparmp;
     ULONG *lparmp;
     USHORT fid;
     ULONG securityInformation;
+    smb_fid_t *fidp;
+    long code = 0;
+    DWORD dwLength;
 
-    parmOffset = smb_GetSMBOffsetParm(inp, 11, 1)
+    /*
+     * For details on the meanings of the various
+     * SMB_COM_TRANSACTION fields, see sections 2.2.4.33
+     * of http://msdn.microsoft.com/en-us/library/ee442092%28PROT.13%29.aspx
+     */
+
+    inTotalParm = smb_GetSMBOffsetParm(inp, 1, 1)
+        | (smb_GetSMBOffsetParm(inp, 2, 1) << 16);
+
+    inTotalData = smb_GetSMBOffsetParm(inp, 3, 1)
+        | (smb_GetSMBOffsetParm(inp, 4, 1) << 16);
+
+    maxParm = smb_GetSMBOffsetParm(inp, 5, 1)
+        | (smb_GetSMBOffsetParm(inp, 6, 1) << 16);
+
+    maxData = smb_GetSMBOffsetParm(inp, 7, 1)
+        | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
+
+    inParm = smb_GetSMBOffsetParm(inp, 9, 1)
+        | (smb_GetSMBOffsetParm(inp, 10, 1) << 16);
+
+    inParmOffset = smb_GetSMBOffsetParm(inp, 11, 1)
         | (smb_GetSMBOffsetParm(inp, 12, 1) << 16);
-    parmp = inp->data + parmOffset;
+
+    inData = smb_GetSMBOffsetParm(inp, 13, 1)
+        | (smb_GetSMBOffsetParm(inp, 14, 1) << 16);
+
+    inDataOffset = smb_GetSMBOffsetParm(inp, 15, 1)
+        | (smb_GetSMBOffsetParm(inp, 16, 1) << 16);
+
+    parmp = inp->data + inParmOffset;
     sparmp = (USHORT *) parmp;
     lparmp = (ULONG *) parmp;
 
     fid = sparmp[0];
     securityInformation = lparmp[1];
 
-    maxData = smb_GetSMBOffsetParm(inp, 7, 1)
-        | (smb_GetSMBOffsetParm(inp, 8, 1) << 16);
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp) {
+        osi_Log2(smb_logp, "smb_ReceiveNTTranQuerySecurityDesc Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
+        return CM_ERROR_BADFD;
+    }
 
-    if (maxData < 36)
-        dataCount = 0;
-    else
-        dataCount = 36;
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_CloseFID(vcp, fidp, NULL, 0);
+        smb_ReleaseFID(fidp);
+        return CM_ERROR_NOSUCHFILE;
+    }
+    lock_ReleaseMutex(&fidp->mx);
+
+    osi_Log4(smb_logp,"smb_ReceiveNTTranQuerySecurityDesc fidp 0x%p scp 0x%p file \"%S\" Info=0x%x",
+             fidp, fidp->scp, osi_LogSaveClientString(smb_logp, fidp->NTopen_wholepathp),
+              securityInformation);
+
+    smb_ReleaseFID(fidp);
+
+    if ( securityInformation & ~(OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION) )
+    {
+        code = CM_ERROR_BAD_LEVEL;
+        goto done;
+    }
+
+    dwLength = sizeof( nullSecurityDesc);
+
+    totalDataCount = dwLength;
+    totalParmCount = 4;
+
+    if (maxData >= totalDataCount) {
+        dataCount = totalDataCount;
+        parmCount = min(totalParmCount, maxParm);
+    } else if (maxParm >= totalParmCount) {
+        totalDataCount = dataCount = 0;
+        parmCount = totalParmCount;
+    } else {
+        totalDataCount = dataCount = 0;
+        totalParmCount = parmCount = 0;
+    }
 
     /* out parms */
     parmOffset = 8*4 + 39;
     parmOffset += 1;   /* pad to 4 */
-    parmCount = 4;
+
     dataOffset = parmOffset + parmCount;
 
     parmSlot = 1;
     outp->oddByte = 1;
     /* Total Parameter Count */
-    smb_SetSMBParmLong(outp, parmSlot, parmCount); parmSlot += 2;
+    smb_SetSMBParmLong(outp, parmSlot, totalParmCount); parmSlot += 2;
     /* Total Data Count */
-    smb_SetSMBParmLong(outp, parmSlot, dataCount); parmSlot += 2;
+    smb_SetSMBParmLong(outp, parmSlot, totalDataCount); parmSlot += 2;
     /* Parameter Count */
     smb_SetSMBParmLong(outp, parmSlot, parmCount); parmSlot += 2;
     /* Parameter Offset */
-    smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
+    smb_SetSMBParmLong(outp, parmSlot, parmCount ? parmOffset : 0); parmSlot += 2;
     /* Parameter Displacement */
     smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
     /* Data Count */
     smb_SetSMBParmLong(outp, parmSlot, dataCount); parmSlot += 2;
     /* Data Offset */
-    smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
+    smb_SetSMBParmLong(outp, parmSlot, dataCount ? dataOffset : 0); parmSlot += 2;
     /* Data Displacement */
     smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-    smb_SetSMBParmByte(outp, parmSlot, 0);     /* Setup Count */
-    smb_SetSMBDataLength(outp, 1 + parmCount + dataCount);
+    /* Setup Count */
+    smb_SetSMBParmByte(outp, parmSlot, 0);
 
-    outData = smb_GetSMBData(outp, NULL);
-    outData++;                 /* round to get to parmOffset */
-    *((ULONG *)outData) = 36; outData += 4;    /* length */
+    if (parmCount == totalParmCount && dwLength == dataCount) {
+        smb_SetSMBDataLength(outp, 1 + parmCount + dataCount);
 
-    if (maxData >= 36) {
-        memcpy(outData, nullSecurityDesc, 36);
-        outData += 36;
-        return 0;
-    } else
-        return CM_ERROR_BUFFERTOOSMALL;
+        /* Data */
+        outData = smb_GetSMBData(outp, NULL);
+        outData++;                     /* round to get to dataOffset */
+
+        *((ULONG *)outData) = dataCount; outData += 4; /* SD Length (4 bytes) */
+        memcpy(outData, nullSecurityDesc, dataCount);
+        outData += dataCount;
+
+        code = 0;
+    } else if (parmCount >= 4) {
+        smb_SetSMBDataLength(outp, 1 + parmCount);
+
+        /* Data */
+        outData = smb_GetSMBData(outp, NULL);
+        outData++;                     /* round to get to dataOffset */
+
+        *((ULONG *)outData) = dwLength; outData += 4;  /* SD Length (4 bytes) */
+        code = CM_ERROR_BUFFERTOOSMALL;
+    } else {
+        smb_SetSMBDataLength(outp, 0);
+        code = CM_ERROR_BUFFER_OVERFLOW;
+    }
+
+  done:
+    return code;
 }
 
 /* SMB_COM_NT_TRANSACT
@@ -9352,3 +9656,23 @@ cm_user_t *smb_FindCMUserByName(clientchar_t *usern, clientchar_t *machine, afs_
     return userp;
 }
 
+cm_user_t *smb_FindCMUserBySID(clientchar_t *usern, clientchar_t *machine, afs_uint32 flags)
+{
+    smb_username_t *unp;
+    cm_user_t *     userp;
+
+    unp = smb_FindUserByName(usern, machine, flags);
+    if (!unp->userp) {
+        lock_ObtainMutex(&unp->mx);
+        unp->flags |= SMB_USERNAMEFLAG_SID;
+        unp->userp = cm_NewUser();
+        lock_ReleaseMutex(&unp->mx);
+        osi_Log2(smb_logp,"smb_FindCMUserBySID New user name[%S] machine[%S]",osi_LogSaveClientString(smb_logp,usern),osi_LogSaveClientString(smb_logp,machine));
+    }  else    {
+        osi_Log2(smb_logp,"smb_FindCMUserBySID Found name[%S] machine[%S]",osi_LogSaveClientString(smb_logp,usern),osi_LogSaveClientString(smb_logp,machine));
+    }
+    userp = unp->userp;
+    cm_HoldUser(userp);
+    smb_ReleaseUsername(unp);
+    return userp;
+}