Windows: Improve SMB detection of Local System account
[openafs.git] / src / WINNT / afsd / smb.c
index 154964d..79b7885 100644 (file)
@@ -15,6 +15,7 @@
 #pragma warning(disable: 4005)
 #include <ntstatus.h>
 #pragma warning(pop)
+#include <sddl.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <malloc.h>
@@ -1230,6 +1231,66 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
     return uidp;
 }              
 
+afs_int32 smb_userIsLocalSystem(smb_user_t *uidp)
+{
+    SID *pSid = NULL;
+    DWORD dwSize1 = 0, dwSize2 = 0;
+    wchar_t *pszRefDomain = NULL;
+    SID_NAME_USE snu = SidTypeGroup;
+    clientchar_t * secSidString = NULL;
+    DWORD gle;
+    afs_int32 isSystem = 0;
+
+    if (uidp->unp->flags & SMB_USERNAMEFLAG_SID) {
+        isSystem = !cm_ClientStrCmp(NTSID_LOCAL_SYSTEM, uidp->unp->name);
+        return isSystem;
+    }
+
+    /*
+     * The input name is not a SID for the user.  See if we can
+     * obtain the SID for the specified name.  If we can, use
+     * that instead of the name provided for the comparison.
+     */
+
+    LookupAccountNameW( NULL /* System Name to begin Search */,
+                        uidp->unp->name,
+                        NULL, &dwSize1,
+                        NULL, &dwSize2,
+                        &snu);
+    gle = GetLastError();
+    if (gle == ERROR_INSUFFICIENT_BUFFER) {
+        pSid = malloc(dwSize1);
+        /*
+         * Although dwSize2 is supposed to include the terminating
+         * NUL character, on Win7 it does not.
+         */
+        pszRefDomain = malloc((dwSize2 + 1) * sizeof(wchar_t));
+    }
+
+    if ( pSid && pszRefDomain ) {
+        memset(pSid, 0, dwSize1);
+
+        if (LookupAccountNameW( NULL /* System Name to begin Search */,
+                                uidp->unp->name,
+                                pSid, &dwSize1,
+                                pszRefDomain, &dwSize2,
+                                &snu))
+            ConvertSidToStringSidW(pSid, &secSidString);
+    }
+
+    if (secSidString) {
+        isSystem = !cm_ClientStrCmp(NTSID_LOCAL_SYSTEM, secSidString);
+        LocalFree(secSidString);
+    }
+
+    if (pSid)
+        free(pSid);
+    if (pszRefDomain)
+        free(pszRefDomain);
+
+    return isSystem;
+}
+
 smb_username_t *smb_FindUserByName(clientchar_t *usern, clientchar_t *machine,
                                    afs_uint32 flags)
 {
@@ -1928,6 +1989,8 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
         fschar_t ftemp[1024];
         clientchar_t * p = shareName; 
         int rw = 0;
+        cm_scache_t * rscp;
+        cm_user_t *userp;
 
         /*  attempt to locate a partial match in root.afs.  This is because
             when using the ANSI RAP calls, the share name is limited to 13 chars
@@ -1942,10 +2005,12 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
         vrock.match = NULL;
         vrock.matchType = 0;
 
-        cm_HoldSCache(cm_data.rootSCachep);
-        code = cm_ApplyDir(cm_data.rootSCachep, smb_FindShareProc, &vrock, &thyper,
-                           (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
-        cm_ReleaseSCache(cm_data.rootSCachep);
+        userp = (uidp? (uidp->unp ? uidp->unp->userp : cm_rootUserp) : cm_rootUserp);
+        rscp = cm_RootSCachep(userp, &req);
+        cm_HoldSCache(rscp);
+        code = cm_ApplyDir(rscp, smb_FindShareProc, &vrock, &thyper,
+                           userp, &req, NULL);
+        cm_ReleaseSCache(rscp);
 
         free(vrock.shareName);
         vrock.shareName = NULL;
@@ -3145,6 +3210,9 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
     else if (code == CM_ERROR_BUFFERTOOSMALL) {
         NTStatus = 0xC0000023L;        /* Buffer too small */
     }
+    else if (code == CM_ERROR_BUFFER_OVERFLOW) {
+        NTStatus = 0x80000005L;        /* Buffer overflow */
+    }
     else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
         NTStatus = 0xC0000035L;        /* Object name collision */
     }   
@@ -3171,12 +3239,16 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
 #ifdef COMMENT
         NTStatus = 0xC000022DL; /* Retry */
 #else
-        NTStatus = 0xC00000B5L; /* I/O Timeout */
+        NTStatus = 0xC0020018L; /* RPC_NT_SERVER_TOO_BUSY */
 #endif
-    } 
+    }
     else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
+#ifdef COMMENT
         NTStatus = 0xC000003AL; /* Path not found */
-    } 
+#else
+        NTStatus = 0xC0020017L; /* RPC_NT_SERVER_UNAVAILABLE */
+#endif
+    }
     else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
        NTStatus = 0xC0000322L; /* No Kerberos key */
     } 
@@ -4075,7 +4147,7 @@ void smb_Daemon(void *parmp)
 
 #ifdef AFS_FREELANCE
             if ( smb_localZero != old_localZero )
-                cm_noteLocalMountPointChange();
+                cm_noteLocalMountPointChange(FALSE);
 #endif
 
            smb_CheckVCs();
@@ -4865,7 +4937,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         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,
                         caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
         if (code == 0) {
 #ifdef DFS_SUPPORT
@@ -5288,10 +5360,10 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     osi_Log1(smb_logp, "SMB receive check path %S",
              osi_LogSaveClientString(smb_logp, pathp));
         
-    rootScp = cm_data.rootSCachep;
-        
     userp = smb_GetUserFromVCP(vcp, inp);
 
+    rootScp = cm_RootSCachep(userp, &req);
+
     caseFold = CM_FLAG_CASEFOLD;
 
     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
@@ -5377,10 +5449,10 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
              dosTime, attribute);
 
-    rootScp = cm_data.rootSCachep;
-        
     userp = smb_GetUserFromVCP(vcp, inp);
 
+    rootScp = cm_RootSCachep(userp, &req);
+
     caseFold = CM_FLAG_CASEFOLD;
 
     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
@@ -5492,10 +5564,10 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     osi_Log1(smb_logp, "SMB receive getfile attributes path %S",
              osi_LogSaveClientString(smb_logp, pathp));
 
-    rootScp = cm_data.rootSCachep;
-        
     userp = smb_GetUserFromVCP(vcp, inp);
 
+    rootScp = cm_RootSCachep(userp, &req);
+
     /* we shouldn't need this for V3 requests, but we seem to */
     caseFold = CM_FLAG_CASEFOLD;
 
@@ -5720,7 +5792,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_data.rootSCachep, pathp, caseFold | CM_FLAG_FOLLOW, userp,
+    code = cm_NameI(cm_RootSCachep(userp, &req), pathp, caseFold | CM_FLAG_FOLLOW, userp,
                     tidPathp, &req, &scp);
         
     if (code) {
@@ -5902,7 +5974,7 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold, userp, tidPathp,
+    code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold, userp, tidPathp,
                     &req, &dscp);
     if (code) {
         cm_ReleaseUser(userp);
@@ -6094,7 +6166,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar
     smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
 
     caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
-    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
+    code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold,
                     userp, tidPathp, &req, &oldDscp);
     if (code) {
         cm_ReleaseUser(userp);
@@ -6114,7 +6186,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar
 #endif /* DFS_SUPPORT */
 
     smb_StripLastComponent(spacep->wdata, &newLastNamep, newPathp);
-    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
+    code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold,
                     userp, tidPathp, &req, &newDscp);
 
     if (code) {
@@ -6304,7 +6376,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar_t
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
     
-    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
+    code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold,
                     userp, tidPathp, &req, &oldDscp);
     if (code) {
         cm_ReleaseUser(userp);
@@ -6324,7 +6396,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar_t
 #endif /* DFS_SUPPORT */
 
     smb_StripLastComponent(spacep->wdata, &newLastNamep, newPathp);
-    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
+    code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold,
                     userp, tidPathp, &req, &newDscp);
     if (code) {
         cm_ReleaseSCache(oldDscp);
@@ -6551,7 +6623,7 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold | CM_FLAG_FOLLOW,
+    code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold | CM_FLAG_FOLLOW,
                     userp, tidPathp, &req, &dscp);
 
     if (code) {
@@ -6686,7 +6758,7 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_scache_t * scp = fidp->scp;
         cm_HoldSCache(scp);
         lock_ReleaseMutex(&fidp->mx);
-        code = cm_FSync(scp, userp, &req);
+        code = cm_FSync(scp, userp, &req, FALSE);
         cm_ReleaseSCache(scp);
     } else {
         lock_ReleaseMutex(&fidp->mx);
@@ -6834,7 +6906,7 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
         }
         if (smb_AsyncStore != 2) {
             lock_ReleaseMutex(&fidp->mx);
-            code = cm_FSync(scp, userp, &req);
+            code = cm_FSync(scp, userp, &req, FALSE);
             lock_ObtainMutex(&fidp->mx);
         }
     }
@@ -8049,7 +8121,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         return CM_ERROR_NOSUCHPATH;
     }
 
-    code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
+    code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata,
                     caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
                     userp, tidPathp, &req, &dscp);
 
@@ -8188,7 +8260,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold | CM_FLAG_FOLLOW,
+    code = cm_NameI(cm_RootSCachep(userp, &req), spacep->wdata, caseFold | CM_FLAG_FOLLOW,
                     userp, tidPathp, &req, &dscp);
 
     if (code) {
@@ -10661,7 +10733,7 @@ void smb_Init(osi_log_t *logp, int useV3,
 
 #ifdef AFS_FREELANCE_CLIENT
     /* Make sure the root.afs volume has the correct time */
-    cm_noteLocalMountPointChange();
+    cm_noteLocalMountPointChange(FALSE);
 #endif
 
     /* initialize the remote debugging log */