Windows: Only Local System Account may set tokens for alternate ids
authorJeffrey Altman <jaltman@your-file-system.com>
Thu, 12 Aug 2010 05:48:16 +0000 (01:48 -0400)
committerJeffrey Altman <jaltman@openafs.org>
Mon, 16 Aug 2010 05:40:11 +0000 (22:40 -0700)
Only permit tokens to be set for alternate ids from the system
account.

LICENSE MIT

Change-Id: Ibeaf16950b0317db99dfebccb9534697a258db78
Reviewed-on: http://gerrit.openafs.org/2541
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>

src/WINNT/afsd/cm_ioctl.h
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h
src/WINNT/afsd/smb_ioctl.c

index 33a71dc..d44c14e 100644 (file)
@@ -138,6 +138,10 @@ extern const int  utf8_prefix_size;
 #define AFSCALL_RXSTATS_DISABLE 0x2     /* Disable RX stats */
 #define AFSCALL_RXSTATS_CLEAR   0x4     /* Clear RX stats */
 
+/* pioctl flags */
+
+#define AFSCALL_FLAG_LOCAL_SYSTEM 0x1
+
 #ifndef __CM_IOCTL_INTERFACES_ONLY__
 
 extern void cm_InitIoctl(void);
index 8261fd7..5f6f657 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,63 @@ 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;
+
+    /*
+     * The input name is probably not a SID for the user which is how
+     * the user is now being identified as a result of the SMB
+     * extended authentication.  See if we can obtain the SID for the
+     * specified name.  If we can, use that instead of the name
+     * provided.
+     */
+
+    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)
 {
index a5a7bf0..71fbc06 100644 (file)
@@ -170,6 +170,8 @@ typedef struct smb {
 #define NTNEGOTIATE_CAPABILITY_COMPRESSED              0x40000000L
 #define NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY       0x80000000L
 
+#define NTSID_LOCAL_SYSTEM L"S-1-5-18"
+
 /* a packet structure for receiving SMB messages; locked by smb_globalLock.
  * Most of the work involved is in handling chained requests and responses.
  *
@@ -600,6 +602,8 @@ extern void smb_ReleaseTID(smb_tid_t *tidp, afs_uint32 locked);
 
 extern smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags);
 
+extern afs_int32 smb_userIsLocalSystem(smb_user_t *userp);
+
 extern smb_username_t *smb_FindUserByName(clientchar_t *usern, clientchar_t *machine, afs_uint32 flags);
 
 extern cm_user_t *smb_FindCMUserByName(clientchar_t *usern, clientchar_t *machine, afs_uint32 flags);
index f085ba2..85216ff 100644 (file)
@@ -205,21 +205,37 @@ smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
     afs_int32 leftToCopy;
     char *op;
     afs_int32 code;
-    cm_user_t *userp;
+    smb_user_t *uidp;
+    cm_user_t *userp = NULL;
+    smb_t *smbp;
+    int isSystem = 0;
 
     iop = fidp->ioctlp;
     count = smb_GetSMBParm(inp, 1);
-    userp = smb_GetUserFromVCP(vcp, inp);
+
+    /* Get the user and determine if it is the local machine account */
+    smbp = (smb_t *) inp;
+    uidp = smb_FindUID(vcp, smbp->uid, 0);
+    if (uidp) {
+        isSystem = smb_userIsLocalSystem(uidp);
+        userp = smb_GetUserFromUID(uidp);
+        smb_ReleaseUID(uidp);
+    }
+
+    if (!userp) {
+        userp = cm_rootUserp;
+        cm_HoldUser(userp);
+    }
 
     /* Identify tree */
     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp);
-    if(code) {
+    if (code) {
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
 
     /* turn the connection around, if required */
-    code = smb_IoctlPrepareRead(fidp, iop, userp, 0);
+    code = smb_IoctlPrepareRead(fidp, iop, userp, isSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
 
     if (code) {
         cm_ReleaseUser(userp);
@@ -1016,7 +1032,7 @@ smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pf
         uname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
         tp += strlen(tp) + 1;
 
-        if (flags & PIOCTL_LOGON) {
+        if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
             /* SMB user name with which to associate tokens */
             smbname = cm_ParseIoctlStringAlloc(&ioctlp->ioctl, tp);
             osi_Log2(smb_logp,"cm_IoctlSetToken for user [%S] smbname [%S]",
@@ -1040,7 +1056,7 @@ smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pf
         osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
     }
 
-    if (flags & PIOCTL_LOGON) {
+    if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
         userp = smb_FindCMUserByName(smbname, ioctlp->fidp->vcp->rname,
                                     SMB_FLAG_CREATE|SMB_FLAG_AFSLOGON);
        release_userp = 1;
@@ -1077,7 +1093,7 @@ smb_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp, afs_uint32 pf
     ucellp->flags |= CM_UCELLFLAG_RXKAD;
     lock_ReleaseMutex(&userp->mx);
 
-    if (flags & PIOCTL_LOGON) {
+    if ((pflags & AFSCALL_FLAG_LOCAL_SYSTEM) && (flags & PIOCTL_LOGON)) {
         ioctlp->ioctl.flags |= CM_IOCTLFLAG_LOGON;
     }