windows-pioctl-update-20050804
authorJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 4 Aug 2005 17:03:50 +0000 (17:03 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 4 Aug 2005 17:03:50 +0000 (17:03 +0000)
change "fs wscell" to report the registry configured cell name when
using freelance mode.

change "fs mkmount|rmmount" to require membership in AFS Client Admins
group when freelance mode is being used

change "symlink make|remove" to require membership in AFS Client Admins
group when freelance mode is being used

Move some smb init debug messages to afsd_init.log

src/WINNT/afsd/afsd_init.c
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/fs.c
src/WINNT/afsd/smb.c
src/WINNT/afsd/symlink.c

index 37189ec..03dacb7 100644 (file)
@@ -139,7 +139,7 @@ afsi_start()
     char wd[256];
     char t[100], u[100], *p, *path;
     int zilch;
-    int code;
+    DWORD code;
     DWORD dwLow, dwHigh;
     HKEY parmKey;
     DWORD dummyLen;
index 7a09cb6..1d09f9c 100644 (file)
@@ -1214,15 +1214,16 @@ long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
        long code = 0;
 
        if (cm_freelanceEnabled) {
-           StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root");
-               ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
+            if (cm_GetRootCellName(ioctlp->outDatap))
+                StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root");
+            ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
        } else if (cm_data.rootCellp) {
            /* return the default cellname to the caller */
            StringCbCopyA(ioctlp->outDatap, 999999, cm_data.rootCellp->name);
            ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
        } else {
            /* if we don't know our default cell, return failure */
-               code = CM_ERROR_NOSUCHCELL;
+            code = CM_ERROR_NOSUCHCELL;
     }
 
     return code;
index eb7bff8..5c7d0ad 100644 (file)
@@ -271,6 +271,22 @@ InAFS(char *apath)
     return 1;
 }
 
+static int 
+IsFreelanceRoot(char *apath)
+{
+    struct ViceIoctl blob;
+    afs_int32 code;
+
+    blob.in_size = 0;
+    blob.out_size = MAXSIZE;
+    blob.out = space;
+
+    code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1);
+    if (code == 0)
+        return !strcmp("Freelance.Local.Root",space);
+    return 1;   /* assume it is because it is more restrictive that way */
+}
+
 /* return a static pointer to a buffer */
 static char *
 Parent(char *apath)
@@ -690,9 +706,27 @@ AclToString(struct Acl *acl)
     return mydata;
 }
 
+static DWORD IsFreelance(void)
+{
+    HKEY  parmKey;
+    DWORD code;
+    DWORD dummyLen;
+    DWORD enabled = 0;
+
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
+                         0, KEY_QUERY_VALUE, &parmKey);
+    if (code == ERROR_SUCCESS) {
+        dummyLen = sizeof(cm_freelanceEnabled);
+        code = RegQueryValueEx(parmKey, "FreelanceClient", NULL, NULL,
+                            (BYTE *) &enabled, &dummyLen);
+        RegCloseKey (parmKey);
+    }
+    return enabled;
+}
+
 #define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins"
 
-BOOL IsAdmin (void)
+static BOOL IsAdmin (void)
 {
     static BOOL fAdmin = FALSE;
     static BOOL fTested = FALSE;
@@ -1750,6 +1784,7 @@ MakeMountCmd(struct cmd_syndesc *as, char *arock)
     struct vldbentry vldbEntry;
 #endif /* not WIN32 */
     struct ViceIoctl blob;
+    char * parent;
 
     /*
 
@@ -1786,11 +1821,17 @@ MakeMountCmd(struct cmd_syndesc *as, char *arock)
         volName = ++tmpName;
     }
 
-    if (!InAFS(Parent(as->parms[0].items->data))) {
+    parent = Parent(as->parms[0].items->data);
+    if (!InAFS(parent)) {
        fprintf(stderr,"%s: mount points must be created within the AFS file system\n", pn);
        return 1;
     }
 
+    if ( IsFreelanceRoot(parent) && !IsAdmin() ) {
+       fprintf(stderr,"%s: Only AFS Client Administrators may alter the root.afs volume\n", pn);
+       return 1;
+    }
+
     if (!cellName) {
        blob.in_size = 0;
        blob.out_size = MAXSIZE;
@@ -1901,7 +1942,14 @@ RemoveMountCmd(struct cmd_syndesc *as, char *arock) {
             error = 1;
            continue;   /* don't bother trying */
        }
-       blob.out_size = 0;
+
+        if ( IsFreelanceRoot(Parent(tp)) && !IsAdmin() ) {
+            fprintf(stderr,"%s: Only AFS Client Administrators may alter the root.afs volume\n", pn);
+            error = 1;
+            continue;   /* skip */
+        }
+
+        blob.out_size = 0;
        blob.in = tp;
        blob.in_size = strlen(tp)+1;
        code = pioctl(tbuffer, VIOC_AFS_DELETE_MT_PT, &blob, 0);
index 4892c2a..5042c51 100644 (file)
@@ -7748,7 +7748,7 @@ void smb_NetbiosInit()
         ncbp->ncb_length = sizeof(lana_list);
         code = Netbios(ncbp);
         if (code != 0) {
-            osi_Log1(smb_logp, "Netbios NCBENUM error code %d", code);
+            afsi_log("Netbios NCBENUM error code %d", code);
             osi_panic(s, __FILE__, __LINE__);
         }
     }
@@ -7769,10 +7769,10 @@ void smb_NetbiosInit()
         if (code == 0) 
             code = ncbp->ncb_retcode;
         if (code != 0) {
-            osi_Log2(smb_logp, "Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code);
+            afsi_log("Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code);
             lana_list.lana[i] = 255;  /* invalid lana */
         } else {
-            osi_Log1(smb_logp, "Netbios NCBRESET lana %d succeeded", lana_list.lana[i]);
+            afsi_log("Netbios NCBRESET lana %d succeeded", lana_list.lana[i]);
         }
     }
 #else
@@ -7794,7 +7794,7 @@ void smb_NetbiosInit()
     len=lstrlen(smb_localNamep);
     memset(smb_sharename,' ',NCBNAMSZ);
     memcpy(smb_sharename,smb_localNamep,len);
-    osi_Log1(smb_logp, "lana_list.length %d", lana_list.length);
+    afsi_log("lana_list.length %d", lana_list.length);
 
     /* Keep the name so we can unregister it later */
     for (l = 0; l < lana_list.length; l++) {
@@ -7809,18 +7809,18 @@ void smb_NetbiosInit()
         code = Netbios(ncbp, dos_ncb);
 #endif /* !DJGPP */
           
-        osi_Log4(smb_logp, "Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d",
+        afsi_log("Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d",
                  lana, code, ncbp->ncb_retcode, ncbp->ncb_cmd_cplt);
         {
             char name[NCBNAMSZ+1];
             name[NCBNAMSZ]=0;
             memcpy(name,ncbp->ncb_name,NCBNAMSZ);
-            osi_Log1(smb_logp, "Netbios NCBADDNAME added new name >%s<",osi_LogSaveString(smb_logp, name));
+            afsi_log("Netbios NCBADDNAME added new name >%s<",name);
         }
 
         if (code == 0) code = ncbp->ncb_retcode;
         if (code == 0) {
-            osi_Log1(smb_logp, "Netbios NCBADDNAME succeeded on lana %d\n", lana);
+            afsi_log("Netbios NCBADDNAME succeeded on lana %d\n", lana);
 #ifdef DJGPP
             /* we only use one LANA with djgpp */
             lana_list.lana[0] = lana;
@@ -7828,13 +7828,13 @@ void smb_NetbiosInit()
 #endif   
         }
         else {
-            osi_Log2(smb_logp, "Netbios NCBADDNAME lana %d error code %d", lana, code);
+            afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code);
             if (code == NRC_BRIDGE) {    /* invalid LANA num */
                 lana_list.lana[l] = 255;
                 continue;
             }
             else if (code == NRC_DUPNAME) {
-                osi_Log0(smb_logp, "Name already exists; try to delete it");
+                afsi_log("Name already exists; try to delete it");
                 memset(ncbp, 0, sizeof(*ncbp));
                 ncbp->ncb_command = NCBDELNAME;
                 memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
@@ -7847,7 +7847,7 @@ void smb_NetbiosInit()
                 if (code == 0) 
                     code = ncbp->ncb_retcode;
                 else {
-                    osi_Log2(smb_logp, "Netbios NCBDELNAME lana %d error code %d\n", lana, code);
+                    afsi_log("Netbios NCBDELNAME lana %d error code %d\n", lana, code);
                 }
                 if (code != 0 || delname_tried) {
                     lana_list.lana[l] = 255;
@@ -7861,7 +7861,7 @@ void smb_NetbiosInit()
                 }
             }
             else {
-                osi_Log2(smb_logp, "Netbios NCBADDNAME lana %d error code %d", lana, code);
+                afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code);
                 lana_list.lana[l] = 255;  /* invalid lana */
                 osi_panic(s, __FILE__, __LINE__);
             }
@@ -8192,11 +8192,10 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
                     sprintf(message,"MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x",
                                        nts, ntsEx);
                     OutputDebugString(message);
-                    osi_Log2(smb_logp,"MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x",
-                              nts, ntsEx);
+                    afsi_log(message);
                 } else {
                     OutputDebugString("MsV1_0SetProcessOption success");
-                    osi_Log0(smb_logp,"MsV1_0SetProcessOption success");
+                    afsi_log("MsV1_0SetProcessOption success");
                 }
                 /* END - code from Larry */
 
index 0b7322a..4ab4cda 100644 (file)
@@ -18,6 +18,7 @@
 #include <time.h>
 #include <winsock2.h>
 #include <errno.h>
+#include <assert.h>
 
 #include <osi.h>
 #include <afsint.h>
@@ -57,8 +58,8 @@ foldcmp (a, b)
 }
 
 /* this function returns TRUE (1) if the file is in AFS, otherwise false (0) */
-static int InAFS(apath)
-register char *apath; {
+static int InAFS(register char *apath)
+{
     struct ViceIoctl blob;
     register afs_int32 code;
 
@@ -68,11 +69,167 @@ register char *apath; {
 
     code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1);
     if (code) {
-       if ((errno == EINVAL) || (errno == ENOENT)) return 0;
+       if ((errno == EINVAL) || (errno == ENOENT)) 
+            return 0;
     }
     return 1;
 }
 
+static int 
+IsFreelanceRoot(char *apath)
+{
+    struct ViceIoctl blob;
+    afs_int32 code;
+
+    blob.in_size = 0;
+    blob.out_size = MAXSIZE;
+    blob.out = space;
+
+    code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1);
+    if (code == 0)
+        return !strcmp("Freelance.Local.Root",space);
+    return 1;   /* assume it is because it is more restrictive that way */
+}
+
+#define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins"
+
+static BOOL IsAdmin (void)
+{
+    static BOOL fAdmin = FALSE;
+    static BOOL fTested = FALSE;
+
+    if (!fTested)
+    {
+        /* Obtain the SID for the AFS client admin group.  If the group does
+         * not exist, then assume we have AFS client admin privileges.
+         */
+        PSID psidAdmin = NULL;
+        DWORD dwSize, dwSize2;
+        char pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ];
+        char *pszRefDomain = NULL;
+        SID_NAME_USE snu = SidTypeGroup;
+
+        dwSize = sizeof(pszAdminGroup);
+
+        if (!GetComputerName(pszAdminGroup, &dwSize)) {
+            /* Can't get computer name.  We return false in this case.
+               Retain fAdmin and fTested. This shouldn't happen.*/
+            return FALSE;
+        }
+
+        dwSize = 0;
+        dwSize2 = 0;
+
+        strcat(pszAdminGroup,"\\");
+        strcat(pszAdminGroup, AFSCLIENT_ADMIN_GROUPNAME);
+
+        LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu);
+        /* that should always fail. */
+
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+            /* if we can't find the group, then we allow the operation */
+            fAdmin = TRUE;
+            return TRUE;
+        }
+
+        if (dwSize == 0 || dwSize2 == 0) {
+            /* Paranoia */
+            fAdmin = TRUE;
+            return TRUE;
+        }
+
+        psidAdmin = (PSID)malloc(dwSize); memset(psidAdmin,0,dwSize);
+        assert(psidAdmin);
+        pszRefDomain = (char *)malloc(dwSize2);
+        assert(pszRefDomain);
+
+        if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) {
+            /* We can't lookup the group now even though we looked it up earlier.  
+               Could this happen? */
+            fAdmin = TRUE;
+        } else {
+            /* Then open our current ProcessToken */
+            HANDLE hToken;
+
+            if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken))
+            {
+
+                if (!CheckTokenMembership(hToken, psidAdmin, &fAdmin)) {
+                    /* We'll have to allocate a chunk of memory to store the list of
+                     * groups to which this user belongs; find out how much memory
+                     * we'll need.
+                     */
+                    DWORD dwSize = 0;
+                    PTOKEN_GROUPS pGroups;
+
+                    GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize);
+
+                    pGroups = (PTOKEN_GROUPS)malloc(dwSize);
+                    assert(pGroups);
+
+                    /* Allocate that buffer, and read in the list of groups. */
+                    if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize))
+                    {
+                        /* Look through the list of group SIDs and see if any of them
+                         * matches the AFS Client Admin group SID.
+                         */
+                        size_t iGroup = 0;
+                        for (; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup)
+                        {
+                            if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid)) {
+                                fAdmin = TRUE;
+                            }
+                        }
+                    }
+
+                    if (pGroups)
+                        free(pGroups);
+                }
+
+                /* if do not have permission because we were not explicitly listed
+                 * in the Admin Client Group let's see if we are the SYSTEM account
+                 */
+                if (!fAdmin) {
+                    PTOKEN_USER pTokenUser;
+                    SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
+                    PSID pSidLocalSystem = 0;
+                    DWORD gle;
+
+                    GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
+
+                    pTokenUser = (PTOKEN_USER)malloc(dwSize);
+                    assert(pTokenUser);
+
+                    if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
+                        gle = GetLastError();
+
+                    if (AllocateAndInitializeSid( &SIDAuth, 1,
+                                                  SECURITY_LOCAL_SYSTEM_RID,
+                                                  0, 0, 0, 0, 0, 0, 0,
+                                                  &pSidLocalSystem))
+                    {
+                        if (EqualSid(pTokenUser->User.Sid, pSidLocalSystem)) {
+                            fAdmin = TRUE;
+                        }
+
+                        FreeSid(pSidLocalSystem);
+                    }
+
+                    if ( pTokenUser )
+                        free(pTokenUser);
+                }
+            }
+        }
+
+        free(psidAdmin);
+        free(pszRefDomain);
+
+        fTested = TRUE;
+    }
+
+    return fAdmin;
+}
+
 /* return a static pointer to a buffer */
 static char *Parent(apath)
 char *apath; {
@@ -230,12 +387,20 @@ static MakeLinkCmd(as)
 register struct cmd_syndesc *as; {
     register afs_int32 code;
     struct ViceIoctl blob;
+    char * parent;
 
-    if (!InAFS(Parent(as->parms[0].items->data))) {
+    parent = Parent(as->parms[0].items->data);
+
+    if (!InAFS(parent)) {
        fprintf(stderr,"%s: symlinks must be created within the AFS file system\n", pn);
        return 1;
     }
 
+    if ( IsFreelanceRoot(parent) && !IsAdmin() ) {
+       fprintf(stderr,"%s: Only AFS Client Administrators may alter the root.afs volume\n", pn);
+       return 1;
+    }
+
     strcpy(space, as->parms[1].items->data);
 #ifdef WIN32
     /* create symlink with a special pioctl for Windows NT, since it doesn't
@@ -299,12 +464,19 @@ register struct cmd_syndesc *as; {
        code = pioctl(tbuffer, VIOC_LISTSYMLINK, &blob, 0);
        if (code) {
            if (errno == EINVAL)
-               fprintf(stderr,"fs: '%s' is not a symlink.\n", ti->data);
+               fprintf(stderr,"symlink: '%s' is not a symlink.\n", ti->data);
            else {
                Die(errno, ti->data);
            }
            continue;   /* don't bother trying */
        }
+
+        if ( IsFreelanceRoot(Parent(tp)) && !IsAdmin() ) {
+            fprintf(stderr,"symlink: Only AFS Client Administrators may alter the root.afs volume\n");
+            code = 1;
+            continue;   /* skip */
+        }
+
        blob.out_size = 0;
        blob.in = tp;
        blob.in_size = strlen(tp)+1;
@@ -312,7 +484,6 @@ register struct cmd_syndesc *as; {
        if (code) {
            Die(errno, ti->data);
        }
-
     }
     return code;
 }